feat(gvg): 组建期

This commit is contained in:
luying
2023-01-05 19:18:56 +08:00
parent 94c69089ac
commit 03fa74f3d1
50 changed files with 10354 additions and 38 deletions

View File

@@ -33,6 +33,7 @@ import { loadGmDb } from './app/db';
import { loadActivities } from './app/services/activity/activityRemoteService';
import { checkAndSetApiIsClose } from './app/services/chatService';
import { initGuildActivityIndexInPinus, resetJoinWoodenHorse } from './app/services/guildActivity/guildActivityService';
import { setGVGServerGroup } from './app/services/gvg/gvgService';
const filePath = (_pinus as any).FILEPATH;
filePath.MASTER = '/config/master';
@@ -192,6 +193,7 @@ async function treatStartLogic(app: _pinus.Application) {
if(app.getServerType() == 'guild') {
initGuildActivityIndexInPinus()
.then(resetJoinWoodenHorse);
setGVGServerGroup();
}
if(app.getServerType() == 'battle'|| app.getServerType() == 'role'|| app.getServerType() == 'connector') {
timeTaskService.setPvpSeasonNum();

View File

@@ -142,6 +142,8 @@ export class EntryHandler {
session.push('vipStartTime', () => { });
session.push('channel', () => { });
assignServer(role.roleId, session);
console.log('#####', role.serverId, role.guildCode)
// console.log(role.guildCode)
// session.push('rid', function (err) {
// if (err) {

View File

@@ -1,5 +1,5 @@
import { Application, BackendSession, pinus } from 'pinus';
import { getRandSingleEelm, resResult } from '../../../pubUtils/util';
import { getRandSingleEelm, isTimestamp, resResult } from '../../../pubUtils/util';
import { STATUS } from '../../../consts/statusCode';
import { GMMailModel, GMMailType } from '../../../db/GMMail';
import { ACTIVITY_TYPE, GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE, MEMORY_LOG_TYPE, PUSH_ROUTE, SURVEY_SELECT } from '../../../consts';
@@ -17,6 +17,12 @@ import { getSurvey } from '../../../services/gmService';
import { sendMessageToAllWithSuc } from '../../../services/pushService';
import { sendMailByContent, sendMailsByGmMail } from '../../../services/mailService';
import { saveMemory } from '../../../services/log/memoryLogService';
import { getGVGConfigFromRemote } from '../../../services/gvg/gvgService';
import { GVGServerGroupModel } from '../../../db/GVGServerGroup';
import { isNumber } from 'underscore';
import { group } from 'console';
import { GVGConfigModel } from '../../../db/GVGConfig';
import { ServerlistModel } from '../../../db/Serverlist';
let timer: NodeJS.Timer;
export default function (app: Application) {
@@ -285,4 +291,30 @@ export class GmHandler {
await saveMemory(memoryLogType);
return resResult(STATUS.SUCCESS);
}
async updateGVGServerGroup(msg: { serverId: number[], groupId: number }, session: BackendSession) {
const { serverId: serverIds, groupId } = msg;
if(!isNumber(groupId)) return resResult(STATUS.WRONG_PARMS);
for(let serverId of serverIds) {
if(!isNumber(serverId)) return resResult(STATUS.WRONG_PARMS);
}
let { scheduleTime } = await getGVGConfigFromRemote();
for(let serverId of serverIds) {
await GVGServerGroupModel.updateByServerId(serverId, groupId, scheduleTime);
}
return resResult(STATUS.SUCCESS);
}
async updateGVGConfig(msg: { configId: number, teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number }, session: BackendSession) {
const { configId, teamTime, prepareTime, battleTime, scheduleTime } = msg;
if(!isNumber(configId) || !isTimestamp(teamTime) || !isTimestamp(prepareTime) || !isTimestamp(battleTime) || !isTimestamp(scheduleTime)) {
return resResult(STATUS.WRONG_PARMS);
}
if(teamTime > prepareTime || prepareTime > battleTime || battleTime > scheduleTime) {
return resResult(STATUS.GM_GVG_TIME_ERR);
}
await GVGConfigModel.updateConfig(configId, teamTime, prepareTime, battleTime, scheduleTime);
await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast();
return resResult(STATUS.SUCCESS);
}
}

View File

@@ -30,6 +30,8 @@ import { changeGuildActivity, guildDismisActivity, guildPayQuitGuild } from '../
import { sendMessageToUserWithSuc } from '../../../services/pushService';
import { GuildActiveModel } from '../../../db/GuildActive';
import { leaveRaceActivityToRemote, leaveRaceWhenDismissToRemote, leaveRaceWhenQuitGuildToRemote } from '../../../services/guildActivity/guildActivityService';
import { getGVGInfoInGuild } from '../../../services/gvg/gvgService';
import { guildAbdicateToLeague, guildDismissToLeague, memberQuitGuildToLeague } from '../../../services/gvg/gvgTeamService';
export default function (app: Application) {
@@ -174,7 +176,7 @@ export class GuildHandler {
const { code } = msg;
const select = ['code', 'name', 'notice', 'ceLimit', 'isAuto', 'icon', 'lv', 'memberCnt', 'guildCe'];
const guild = await GuildModel.findByCode(code, serverId, select.join(' '));
const guild = await GuildModel.findByCode(code, null, select.join(' '));
let leader = <RoleType>guild.leader;
delete guild.leader;
// 返回
@@ -199,7 +201,7 @@ export class GuildHandler {
}
// 管理员最大数 等策划表
let guild = await GuildModel.findByCode(code, serverId, 'managerCnt lv');
let guild = await GuildModel.findByCode(code, serverId, 'managerCnt lv leagueCode');
if (!guild) {
return resResult(STATUS.GUILD_NOT_FOUND);
}
@@ -235,6 +237,7 @@ export class GuildHandler {
await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(role) }]);
await RoleModel.updateRoleInfo(memberRoleId, { isGuildLeader: true });
await RoleModel.updateRoleInfo(roleId, { isGuildLeader: false });
await guildAbdicateToLeague(guild, roleId, role);
}
guild = await GuildModel.updateInfo(code, updateObject, { managerCnt: managerCntInc }, 'managerCnt code name'); // 如果有转让团长设置leader
@@ -274,13 +277,14 @@ export class GuildHandler {
return resResult(STATUS.SUCCESS, { hasGuild: false })
};
let guild = await GuildModel.findByCode(userGuild.guildCode, serverId);
let guild = await GuildModel.findByCode(userGuild.guildCode, serverId, '+serverId');
if (!guild) {
return resResult(STATUS.GUILD_NOT_FOUND);
}
let result = await getMyGuildInfo(roleId, sid, userGuild, guild, serverId, session);
return resResult(STATUS.SUCCESS, result);
let gvg = await getGVGInfoInGuild(guild);
return resResult(STATUS.SUCCESS, { ...result, gvg });
}
// 玩家申请公会
@@ -561,6 +565,7 @@ export class GuildHandler {
const { members } = guild;
await RoleModel.dissmissGuild(members);
await UserGuildApplyModel.deleteApplyByGuild(code);
await guildDismissToLeague(guild);
await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast(members.map(roleId => { return { roleId, userGuild: null } })); // 更新session
@@ -602,6 +607,7 @@ export class GuildHandler {
if (!guild) return resResult(STATUS.GUILD_QUIT_ERROR);
await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }])
await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: '' }]);
await memberQuitGuildToLeague(guild, role);
//删除排名信息
await removeBossRank(code, roleId);
@@ -637,7 +643,7 @@ export class GuildHandler {
if (!guild) return resResult(STATUS.GUILD_KICK_ERROR);
await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }])
await updateUserInfo(REDIS_KEY.USER_INFO, memberRoleId, [{ field: 'guildName', value: '' }]);
await memberQuitGuildToLeague(guild, role);
//删除排名信息
await removeBossRank(code, memberRoleId);

View File

@@ -0,0 +1,61 @@
import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus";
import { GVG_PERIOD, GVG_SERVER_TYPE, STATUS } from "../../../consts";
import { GVGLeagueModel } from "../../../db/GVGLeague";
import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare";
import { GVGMainData } from "../../../domain/gvgField/returnData";
import { resResult } from "../../../pubUtils/util";
import { getGVGConfig, getGVGPeriodData, getGVGServerType } from "../../../services/gvg/gvgService";
import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, getMyAuth } from "../../../services/gvg/gvgTeamService";
import { getAllServerName } from "../../../services/redisService";
import { GVGUserDataModel } from "../../../db/GVGUserData";
import { GVGUserItemModel } from "../../../db/GVGUserItem";
import { GVGUserTaskModel } from "../../../db/GVGUserTask";
export default function (app: Application) {
new HandlerService(app, {});
return new GVGHandler(app);
}
export class GVGHandler {
channelService: ChannelService;
constructor(private app: Application) {
this.channelService = app.get('channelService');
}
// 测试
async getData(msg: {}, session: BackendSession) {
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
let { configId, period, countdownTime } = getGVGPeriodData();
let serverType = await getGVGServerType(serverId);
if(serverType == GVG_SERVER_TYPE.NO) return resResult(STATUS.GVG_NO_SERVER_TYPE);
let data = new GVGMainData(configId, period, countdownTime, serverType);
let serverNames = await getAllServerName();
let league = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!league) {
league = await autoCreateLeague(guildCode);
}
if(league) {
data.setLeague(league, serverNames);
let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, league.leagueCode);
data.setLeagueParpare(leaguePrepare);
let userData = await GVGUserDataModel.findByRole(configId, league.leagueCode, roleId);
let items = await GVGUserItemModel.findByRole(configId, league.leagueCode, roleId);
let tasks = await GVGUserTaskModel.findByRole(configId, league.leagueCode, roleId);
data.setPlayerInfo(userData, getMyAuth(league, roleId), await checkCanPrepare(roleId), checkCanChooseJob(userData?.job, leaguePrepare), items, tasks);
}
return resResult(STATUS.SUCCESS, data)
}
async test(msg: { }, session: BackendSession) {
const time = getGVGConfig();
return resResult(STATUS.SUCCESS, { time });
}
}

View File

@@ -0,0 +1,574 @@
import { Application, BackendSession, ChannelService, HandlerService } from "pinus";
import { GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, STATUS } from "../../../consts";
import { resResult } from "../../../pubUtils/util";
import { GuildModel, GuildType } from "../../../db/Guild";
import { UserGuildModel } from "../../../db/UserGuild";
import { GVGLeagueModel, GVGLeagueType } from "../../../db/GVGLeague";
import { GVGLeagueApplyModel } from "../../../db/GVGLeagueApply";
import { getGVGPeriodData, getGVGServerType, getServersOfSameGroup } from "../../../services/gvg/gvgService";
import { checkCanManage, checkGuildLeader, checkLeagueAuth, createLeague, getLeagueApplyData, getLeagueInviteData, getMyAuth, joinGuildToLeague } from "../../../services/gvg/gvgTeamService";
import { LeagueGuildInfo, LeagueListInfo, LeagueMemberListInfo, LeagueSimpleInfo } from "../../../domain/gvgField/returnData";
import { getAllServerName, getServerName } from "../../../services/redisService";
import { GVG } from "../../../pubUtils/dicParam";
import { RoleModel } from "../../../db/Role";
import { GVGUserDataModel } from "../../../db/GVGUserData";
import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../../../services/pushService";
import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare";
export default function (app: Application) {
new HandlerService(app, {});
return new GVGManageHandler(app);
}
export class GVGManageHandler {
channelService: ChannelService;
constructor(private app: Application) {
this.channelService = app.get('channelService');
}
// 创建新联军
async createLeague(msg: { name: string, icon: number, notice: string }, session: BackendSession) {
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const { name, icon, notice } = msg;
const checkNameResult = await GVGLeagueModel.checkName(name);
if (checkNameResult) return resResult(STATUS.LEAGUE_NAME_DUP);
let { period } = getGVGPeriodData();
if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD);
const guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild);
if(checkGuildResult.code != 0) return checkGuildResult;
const league = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(league) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST);
const newLeague = await createLeague(guild, { name, icon, notice });
return resResult(STATUS.SUCCESS, {
leagueCode: newLeague.leagueCode,
hasLeague: true
} );
}
// 获取联军列表
async getLeagues(msg: { page: number, name: string }, session: BackendSession) {
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
const { page, name } = msg;
let serverType = await getGVGServerType(serverId);
if(serverType == GVG_SERVER_TYPE.NO) return resResult(STATUS.GVG_NO_SERVER_TYPE);
const serverNames = await getAllServerName();
let serverIds = await getServersOfSameGroup(serverType, serverId);
const leagues = await GVGLeagueModel.findByCondition(serverType, serverIds, page, name);
const applies = await GVGLeagueApplyModel.findApplyFromGuild(guildCode);
let result: LeagueListInfo[] = [];
for(let league of leagues) {
let data = new LeagueListInfo(league, serverNames);
let hasApply = !!applies.find(cur => cur.leagueCode == league.leagueCode);
data.setHasApply(hasApply);
result.push(data);
}
return resResult(STATUS.SUCCESS, {
leagues: result
} );
}
// 未加入成员查看联军信息
async getLeagueInfo(msg: { leagueCode: string }, session: BackendSession) {
const { leagueCode } = msg;
const guildCode = session.get('guildCode');
const serverNames = await getAllServerName();
const league = await GVGLeagueModel.findByCode(leagueCode);
let result = new LeagueSimpleInfo(league, serverNames)
let hasApply = await GVGLeagueApplyModel.checkApply(leagueCode, guildCode, GVG_APPLY_TYPE.APPLY);
result.setHasApply(hasApply);
// TODO 占领城池
return resResult(STATUS.SUCCESS, {
league: result
} );
}
// 申请加入联军
async applyLeague(msg: { leagueCodes: string[] }, session: BackendSession) {
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
const { leagueCodes } = msg;
// 检查时间
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
const guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild);
if(checkGuildResult.code != 0) return checkGuildResult;
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(myLeague) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST);
const serverNames = await getAllServerName();
const leagues = await GVGLeagueModel.findByCodes(leagueCodes);
let result: LeagueListInfo[] = [];
for(let league of leagues) {
if(league.guildCnt > GVG.GVG_LEAGUE_COMPOSE) continue;
await GVGLeagueApplyModel.createApply(league, guild, GVG_APPLY_TYPE.APPLY);
let data = new LeagueListInfo(league, serverNames);
data.setHasApply(true);
result.push(data);
}
// 返回
return resResult(STATUS.SUCCESS, { leagues: result });
}
// 获取申请列表
async getApplies(msg: {}, session: BackendSession) {
const guildCode = session.get('guildCode');
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const serverNames = await getAllServerName();
const applies = await GVGLeagueApplyModel.findApplyFromLeague(myLeague.leagueCode);
const invitations = await GVGLeagueApplyModel.findInviteFromLeague(myLeague.leagueCode);
let result = applies.map(apply => getLeagueApplyData(apply, serverNames, invitations));
// 返回
return resResult(STATUS.SUCCESS, { guilds: result });
}
// 处理申请
async handleApply(msg: { guildCode: string, isReceive: boolean }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { guildCode: targetGuildCode, isReceive } = msg;
// 检查时间
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
// 权限
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.HANDLE_APPLY);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
if(isReceive) {
let result = await joinGuildToLeague(myLeague, targetGuildCode);
if(result.code == 0) {
myLeague = <GVGLeagueType>result.data;
await GVGLeagueApplyModel.deleteAllGuildApply(targetGuildCode);
} else {
await GVGLeagueApplyModel.deleteApply(targetGuildCode, myLeague.leagueCode);
return result;
}
} else { // 不同意,删除申请
await GVGLeagueApplyModel.deleteApply(targetGuildCode, myLeague.leagueCode);
}
// 返回
return resResult(STATUS.SUCCESS, {
guildCnt: myLeague.guildCnt,
memberCnt: myLeague.memberCnt,
leagueCe: myLeague.leagueCe
});
}
// 获取可以邀请的军团
async getInviteGuilds(msg: { page: number, name: string }, session: BackendSession) {
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
const { page, name } = msg;
// 检查时间
const serverType = await getGVGServerType(serverId);
const checkResult = await checkCanManage(serverId, serverType);
if(checkResult.code != 0) return checkResult;
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const invitations = await GVGLeagueApplyModel.findInviteFromLeague(myLeague.leagueCode);
const serverIds = await getServersOfSameGroup(serverType, serverId);
const serverNames = await getAllServerName();
const guilds = await GuildModel.findGuildsForGVG(page, name, serverIds);
let result = guilds.map(guild => {
let data = new LeagueGuildInfo(guild, serverNames);
let hasInvited = !!invitations.find(cur => cur.guildCode == guild.code);
data.setHasInvited(hasInvited);
return data
});
// 返回
return resResult(STATUS.SUCCESS, {
guilds: result
});
}
// 邀请加入联军
async inviteGuild(msg: { guildCodes: string[] }, session: BackendSession) {
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
const { guildCodes } = msg;
// 必须跨服玩法
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
// 权限
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.INVITE);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
const guilds = await GuildModel.findByCodes(guildCodes);
const serverNames = await getAllServerName();
let result: LeagueGuildInfo[] = [];
for(let guild of guilds) {
await GVGLeagueApplyModel.createApply(myLeague, guild, GVG_APPLY_TYPE.INVITE);
let data = new LeagueGuildInfo(guild, serverNames);
data.setHasInvited(true);
result.push(data);
}
// 返回
return resResult(STATUS.SUCCESS, { guilds: result });
}
// 获取邀请我们军团的联军
async getLeagueInvitations(msg: {}, session: BackendSession) {
const guildCode = session.get('guildCode');
const serverNames = await getAllServerName();
const invitations = await GVGLeagueApplyModel.findInviteFromGuild(guildCode);
const applies = await GVGLeagueApplyModel.findApplyFromGuild(guildCode);
let result: LeagueListInfo[] = invitations.map(apply => getLeagueInviteData(apply, serverNames, applies));
// 返回
return resResult(STATUS.SUCCESS, { leagues: result });
}
// 处理邀请
async handleInvitation(msg: { leagueCode: string, isReceive: boolean }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { leagueCode: targetLeagueCode, isReceive } = msg;
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
// 军团权限
const checkGuildResult = await checkGuildLeader(guildCode, roleId);
if(checkGuildResult.code != 0) return checkGuildResult;
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(myLeague) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST);
const league = await GVGLeagueModel.findByCode(targetLeagueCode);
if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let hasLeague = false;
if(isReceive) {
let result = await joinGuildToLeague(league, guildCode);
if(result.code == 0) {
hasLeague = true;
await GVGLeagueApplyModel.deleteAllGuildApply(guildCode);
} else {
await GVGLeagueApplyModel.deleteInvite(guildCode, league.leagueCode);
return result;
}
} else { // 不同意,删除申请
await GVGLeagueApplyModel.deleteInvite(guildCode, league.leagueCode);
}
// 返回
return resResult(STATUS.SUCCESS, {
leagueCode: targetLeagueCode,
isReceive,
hasLeague
});
}
// 获取组成的所有军团列表
async getGuilds(msg: { leagueCode: string }, session: BackendSession) {
const { leagueCode: targetLeagueCode } = msg;
const league = await GVGLeagueModel.findByCode(targetLeagueCode);
if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const guilds = await GuildModel.findByCodes(league.guildCodes);
const serverNames = await getAllServerName();
const result = guilds.map(guild => {
return new LeagueGuildInfo(guild, serverNames)
});
// 返回
return resResult(STATUS.SUCCESS, {
guilds: result
});
}
// 获取组成的所有玩家列表
async getMembers(msg: { leagueCode: string }, session: BackendSession) {
const { leagueCode: targetLeagueCode } = msg;
const league = await GVGLeagueModel.findByCode(targetLeagueCode);
if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let { configId } = getGVGPeriodData();
const members = league.members||[];
let roleIds = members.map(member => member.roleId);
const roles = await RoleModel.findByRoleIds(roleIds);
const serverNames = await getAllServerName();
const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds);
const result = roles.map(role => {
let obj = new LeagueMemberListInfo(role, serverNames);
let userdata = userdatas.find(userdata => userdata.roleId == role.roleId);
if(userdata) obj.setByUserData(userdata);
let member = members.find(cur => cur.roleId == role.roleId);
if(member) obj.setAuth(member.auth);
return obj;
});
// 返回
return resResult(STATUS.SUCCESS, {
members: result
});
}
// 踢掉某个军团
async kick(msg: { guildCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { guildCode: targetGuildCode } = msg;
// 不能踢自己的军团
if(guildCode == targetGuildCode) return resResult(STATUS.GVG_CANNOUT_KICK_SELF_GUILD);
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
// 权限
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.KICK);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
// 更新对方军团信息
const guild = await GuildModel.quitFromLeague(targetGuildCode, myLeague.leagueCode, '+members');
if(!guild) return resResult(STATUS.GUILD_HAS_QUIT);
// 更新联军信息
myLeague = await GVGLeagueModel.quitGuild(myLeague.leagueCode, guild);
// 发送消息
await sendMessageToGuildWithSuc(targetGuildCode, PUSH_ROUTE.LEAGUE_KICK, { leagueCode: myLeague.leagueCode })
// 返回
return resResult(STATUS.SUCCESS, {
guildCnt: myLeague.guildCnt,
memberCnt: myLeague.memberCnt,
leagueCe: myLeague.leagueCe,
});
}
// 军团退出
async quit(msg: { guildCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { guildCode: targetGuildCode } = msg;
// 检查是否是自己军团
if(guildCode != targetGuildCode) return resResult(STATUS.GVG_CANNOUT_KICK_SELF_GUILD);
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
// 只能团长退出
let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild);
if(checkGuildResult.code != 0) return checkGuildResult;
// 联军盟主不能退出
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.QUIT);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
// 更新对方军团信息
guild = await GuildModel.quitFromLeague(guild.code, myLeague.leagueCode, '+members');
// 更新联军信息
myLeague = await GVGLeagueModel.quitGuild(myLeague.leagueCode, guild);
// 发送消息
await sendMessageToGuildWithSuc(targetGuildCode, PUSH_ROUTE.LEAGUE_KICK, { leagueCode: myLeague.leagueCode })
// 返回
return resResult(STATUS.SUCCESS, {
hasLeague: !!guild.leagueCode
});
}
// 解散联军
async dismiss(msg: { leagueCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { leagueCode: targetLeagueCode } = msg;
const checkResult = await checkCanManage(serverId);
if(checkResult.code != 0) return checkResult;
// 权限
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.LEAGUE_CODE_ERR);
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.DISSMISS);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
// 更新对方军团信息
await GuildModel.dissmissLeague(targetLeagueCode);
// 更新联军信息
await GVGLeagueModel.dismiss(myLeague.leagueCode);
// 发送消息
for(let guildCode of myLeague.guildCodes) {
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_DISSMISS, { leagueCode: myLeague.leagueCode })
}
// 返回
return resResult(STATUS.SUCCESS, {
hasLeague: false
});
}
// 获取可转让的人的列表
async getCandidate(msg: { leagueCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { leagueCode: targetLeagueCode } = msg;
// 权限
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.LEAGUE_CODE_ERR);
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ABDICATE);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
let { configId } = getGVGPeriodData();
const members = myLeague.members||[];
const candidates = members.filter(cur => cur.auth == LEAGUE_AUTH.SUB_LEADER);
let roleIds = candidates.map(member => member.roleId);
const roles = await RoleModel.findByRoleIds(roleIds);
const serverNames = await getAllServerName();
const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds);
const result = roles.map(role => {
let obj = new LeagueMemberListInfo(role, serverNames);
let userdata = userdatas.find(userdata => userdata.roleId == role.roleId);
if(userdata) obj.setByUserData(userdata);
let member = members.find(cur => cur.roleId == role.roleId);
if(member) obj.setAuth(member.auth);
return obj;
});
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, targetLeagueCode);
const { producerCnt, fighterCnt } = leaguePrepare||{ producerCnt: 0, fighterCnt: 0 }
// 返回
return resResult(STATUS.SUCCESS, {
producerCnt, fighterCnt,
members: result
});
}
// 获取可转让的人的列表
async abdicate(msg: { roleId: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { roleId: targetRoleId } = msg;
// 权限
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ABDICATE);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
const checkHisAuth = await checkLeagueAuth(targetRoleId, myLeague, LEAGUE_MANAGE_TYPE.BE_ABDICATED);
if(!checkHisAuth) return resResult(STATUS.GVG_HE_HAS_NO_AUTH);
const targetRole = await RoleModel.findByRoleId(targetRoleId, '_id roleName serverId');
let targetRoleServerName = await getServerName(targetRole.serverId);
// 修改联军数据 membersleader
myLeague = await GVGLeagueModel.abdicate(myLeague.leagueCode, roleId, targetRoleId, targetRole._id);
// 推送
await sendMessageToUserWithSuc(targetRoleId, PUSH_ROUTE.LEAGUE_ABDICATE, { leagueCode: myLeague.leagueCode })
let myAuth = getMyAuth(myLeague, roleId);
// 返回
return resResult(STATUS.SUCCESS, {
auth: myAuth,
leader: {
name: targetRole.roleName,
serverId: targetRole.serverId,
serverName: targetRoleServerName
},
});
}
// 设置联军信息
async setLeagueInfo(msg: { leagueCode: string, name: string, notice: string, icon: number }, session: BackendSession) {
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const { leagueCode: targetLeagueCode, name, notice, icon } = msg;
// 检查名字是否重
if(name != undefined) {
const checkNameResult = await GVGLeagueModel.checkName(name);
if (checkNameResult) return resResult(STATUS.LEAGUE_NAME_DUP);
}
// 权限
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.WRONG_PARMS);
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_INFO);
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
// 修改联军数据
myLeague = await GVGLeagueModel.setInfo(targetLeagueCode, name, notice, icon);
// 返回
return resResult(STATUS.SUCCESS, {
leagueCode: myLeague.leagueCode,
name: myLeague.name,
notice: myLeague.notice,
icon: myLeague.icon,
});
}
}

View File

@@ -6,6 +6,8 @@ import { errlogger } from '../../../util/logger';
import { setApiIsClose } from '../../../services/chatService';
import { setHiddenData } from '../../../services/dataService';
import { setKvToMemory } from '../../../services/pushService';
import { getGVGConfig, setGVGConfig, setGVGServerGroup } from '../../../services/gvg/gvgService';
import { GVGConfigType } from '../../../db/GVGConfig';
export default function (app: Application) {
new HandlerService(app, {});
@@ -92,4 +94,28 @@ export class GuildRemote {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async setGVGConfig(config: GVGConfigType) {
try {
setGVGConfig(config);
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async getGVGConfig() {
try {
return getGVGConfig();
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async setGVGServerGroup() {
try {
return setGVGServerGroup();
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
}

View File

@@ -1,5 +1,5 @@
import { Application, ChannelService } from 'pinus';
import { guildActivityStart, gateActivityEnd, cityActivityEnd, raceActivityEnd, guildActivitySchedule, auctionSchedule, initMaintenance, stopMaintenance, initAutoCreateServer, addMailsToSchedule, updateTimeLimitRank, setLadderCountDown, cancelLadderCountDown, initSumSchedule, setPvpSeasonSchedule } from '../../../services/timeTaskService';
import { guildActivityStart, gateActivityEnd, cityActivityEnd, raceActivityEnd, guildActivitySchedule, auctionSchedule, initMaintenance, stopMaintenance, initAutoCreateServer, addMailsToSchedule, updateTimeLimitRank, setLadderCountDown, cancelLadderCountDown, initSumSchedule, setPvpSeasonSchedule, initGVGConfigSchedule } from '../../../services/timeTaskService';
import PvpDefenseType from '../../../db/PvpDefense';
import { DicGuildActivity } from '../../../pubUtils/dictionary/DicGuildActivity';
import { reloadResources } from '../../../pubUtils/data';
@@ -250,4 +250,12 @@ export class SystimerRemote {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async initGVGConfigSchedule() {
try {
await initGVGConfigSchedule();
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
}

View File

@@ -1602,6 +1602,13 @@ export function checkRouteParam(route: string, msg: any) {
if(!checkNaturalNumbers(msg.stage)) return false;
break;
}
case "battle.ladderHandler.getRec":
{
if(!checkNaturalStrings(msg.name)) return false;
if(!checkStringIfExist(msg.notice)) return false;
if(!checkNaturalNumbers(msg.icon)) return false;
break;
}
case "role.heroHandler.addItem":
{
if(!isDevelopEnv() && !checkNaturalNumbers(msg.id, msg.count)) return false;

View File

@@ -414,4 +414,8 @@ export function getPastTime() {
export function getFutureTime() {
return moment('2100-01-01').unix();
}
export function initServerZone() {
}

View File

@@ -27,6 +27,8 @@ import { RewardInter } from "../pubUtils/interface";
import { getGuildFundByRefTime } from "./donateService";
import { BattleRecordModel } from "../db/BattleRecord";
import { BossInstanceModel } from "../db/BossInstance";
import { pick } from "underscore";
import { memberJoinGuildToLeague } from "./gvg/gvgTeamService";
export async function getMyGuildInfo(roleId: string, sid: string, userGuild: UserGuildType, guild: GuildType, serverId: number, session: FrontendOrBackendSession) {
@@ -51,7 +53,7 @@ export async function getMyGuildInfo(roleId: string, sid: string, userGuild: Use
let guildActive = await getTodayGuildActive(guild.code);
// 返回
return { hasGuild: true, guildMemberMax, ...guild, activeDaily: guildActive, leader: { ...leader, isOnline: leaderIsOnline }, rank, myInfo: { ...userGuild } };
return { hasGuild: true, guildMemberMax, ...guild, activeDaily: guildActive, leader: { ...pick(leader, ['ce', 'lv', 'quitTime', 'roleId', 'roleName', 'head', 'frame', 'spine', 'title', 'isOnline']), isOnline: leaderIsOnline }, rank, myInfo: { ...userGuild } };
}
/**
@@ -116,6 +118,7 @@ export async function joinGuild(code: string, guildName: string, lv: number, rol
return { status: -1, resResult: resResult(STATUS.GUILD_HAS_JOIN) };
}
await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: guildName }]);
await memberJoinGuildToLeague(guild, role);
const userGuild = await UserGuildModel.createUserGuild(guild.code, role, false);
if (!userGuild) {

View File

@@ -0,0 +1,179 @@
import { pinus } from "pinus";
import { GVGConfigModel, GVGConfigType } from "../../db/GVGConfig";
import { getTimeFun, getZeroPoint, getZeroPointOfTime, nowSeconds, WEEK_TO_SECOND } from "../../pubUtils/timeUtil";
import { getAllServerCreateTime, getServerCreateTime } from "../redisService";
import { GVG_PERIOD, GVG_SERVER_TYPE, SHOP_REFRESH_TYPE } from "../../consts";
import { GVGLeagueModel } from "../../db/GVGLeague";
import { GVGLeaguePrepareModel } from "../../db/GVGLeaguePrepare";
import { GVGServerGroupModel } from "../../db/GVGServerGroup";
import { gameData } from "../../pubUtils/data";
import { getRandSingleEelm } from "../../pubUtils/util";
import { GVG } from "../../pubUtils/dicParam";
import { ServerlistModel } from "../../db/Serverlist";
import { GuildType } from "../../db/Guild";
// 定时器相关
export async function createNewGVGConfig() {
let { teamTime, prepareTime, battleTime, scheduleTime } = getPeriodTime();
const config = await GVGConfigModel.createNewConfig(teamTime, prepareTime, battleTime, scheduleTime);
setGVGConfigToRemote(config);
// TODO 每周自动解散一些联军
await pinus.app.rpc.guild.guildRemote.setGVGServerGroup.broadcast();
return config;
}
// 获取各个周期的时间大约每周日5点的时候刷的
export function getPeriodTime() {
let now = new Date();
let curDay = now.getDay(); // 今天星期几
let teamConfig = gameData.gvgPeriod.get(GVG_PERIOD.TEAM);
let prepareConfig = gameData.gvgPeriod.get(GVG_PERIOD.PREPARE);
let battleConfig = gameData.gvgPeriod.get(GVG_PERIOD.BATTLE);
// 如果现在是周日,那么就是本周期的组队开始时间,如果是其他日子(启动初始化),就是下周期的组队开始时间
let _teamTime = <number>getTimeFun().getTimeWithWeek(teamConfig.startDay, teamConfig.startHour, teamConfig.startMinute, teamConfig.startSecond);
let _prepareTime = <number>getTimeFun().getTimeWithWeek(prepareConfig.startDay, prepareConfig.startHour, prepareConfig.startMinute, prepareConfig.startSecond);
let _battleTime = <number>getTimeFun().getTimeWithWeek(battleConfig.startDay, battleConfig.startHour, battleConfig.startMinute, battleConfig.startSecond);
console.log('_teamTime: ', _teamTime);
let teamTime = curDay == 0? _teamTime: _teamTime - 7 * 86400;
let prepareTime = curDay == 0? _prepareTime + 7 * 86400: _prepareTime;
let battleTime = curDay == 0? _battleTime + 7 * 86400: _battleTime;
let scheduleTime = teamTime + 7 * 86400;
return { teamTime, prepareTime, battleTime, scheduleTime }
}
export async function getGVGConfigFromRemote() {
let guildServers = pinus.app.getServersByType('guild');
let server = getRandSingleEelm(guildServers);
return await pinus.app.rpc.guild.guildRemote.getGVGConfig.toServer(server.id);
}
export function setGVGConfigToRemote(config: GVGConfigType) {
if(!config) return null
pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config);
}
export function setGVGConfig(config: GVGConfigType) {
if(!config) return null
pinus.app.set('gvgConfigId', config.configId);
pinus.app.set('gvgTeamTime', config.teamTime);
pinus.app.set('gvgPrepareTime', config.prepareTime);
pinus.app.set('gvgBattleTime', config.battleTime);
pinus.app.set('gvgScheduleTime', config.scheduleTime);
}
export function getGVGConfig() {
let configId = pinus.app.get('gvgConfigId');
let teamTime = pinus.app.get('gvgTeamTime');
let prepareTime = pinus.app.get('gvgPrepareTime');
let battleTime = pinus.app.get('gvgBattleTime');
let scheduleTime = pinus.app.get('gvgScheduleTime');
return { configId, teamTime, prepareTime, battleTime, scheduleTime }
}
function getServerTypeByTime(openTime: number) {
let today = nowSeconds();
if(today - openTime < WEEK_TO_SECOND) return GVG_SERVER_TYPE.NO;
let toWeek = getCurrentTeamTime(today);
let openWeek = getCurrentTeamTime(openTime);
let n = Math.floor((toWeek - openWeek) / WEEK_TO_SECOND);
return n <= GVG.GVG_CROSS_SERVICE_STARTTIME? GVG_SERVER_TYPE.SINGLE: GVG_SERVER_TYPE.MULTI;
}
function getCurrentTeamTime(time: number) {
let teamConfig = gameData.gvgPeriod.get(GVG_PERIOD.TEAM);
// 本周日
let _teamTime = <number>getTimeFun(time).getTimeWithWeek(teamConfig.startDay, teamConfig.startHour, teamConfig.startMinute, teamConfig.startSecond);
return _teamTime > time? _teamTime - WEEK_TO_SECOND: _teamTime;
}
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();
let period = getCurPeriod();
let countdownTime = teamTime;
switch(period) {
case GVG_PERIOD.TEAM: {
countdownTime = prepareTime; break;
}
case GVG_PERIOD.PREPARE: {
countdownTime = battleTime; break;
}
case GVG_PERIOD.BATTLE: {
countdownTime = scheduleTime; break;
}
}
return { configId, period, countdownTime };
}
export function getCurPeriod() {
let { teamTime, prepareTime, battleTime } = getGVGConfig();
let now = nowSeconds();
if(now >= teamTime && now < prepareTime) {
return GVG_PERIOD.TEAM;
} else if (now >= prepareTime && now < battleTime) {
return GVG_PERIOD.PREPARE;
} else {
return GVG_PERIOD.BATTLE;
}
}
export async function initLeaguePrepare() {
const { configId } = getGVGConfig();
const leagues = await GVGLeagueModel.findAllLeague();
for(let { leagueCode, memberCnt } of leagues) {
await GVGLeaguePrepareModel.initData(configId, leagueCode, memberCnt);
}
}
export async function setGVGServerGroup() {
const servers = await ServerlistModel.findByEnv(pinus.app.get('env'));
const serverGroups = await GVGServerGroupModel.findByTime(nowSeconds());
pinus.app.set('gvgServerGroup', servers.map(obj => {
let server = serverGroups.find(cur => cur.serverId == obj.serverId);
return { serverId: obj.id, groupId: server? server.groupId: obj.groupId }
}));
}
// 查询本小区所在的战区
// gvgServerGroup: id-小区唯一id serverId-小区在大区下的id
export async function getGroupIdOfServer(id: number) {
let arr: { serverId: number; groupId: number }[] = pinus.app.get('gvgServerGroup')||[];
let obj = arr.find(cur => cur.serverId == id);
return obj?.groupId||0;
}
// 查询当前和本小区同一个战区的其他小区
export async function getServersOfSameGroup(type: GVG_SERVER_TYPE, id: number) {
if(type == GVG_SERVER_TYPE.SINGLE) return [id];
let groupId = await getGroupIdOfServer(id);
let arr: { serverId: number; groupId: number }[] = pinus.app.get('gvgServerGroup')||[];
let serverCreateTimes = await getAllServerCreateTime();
return arr.filter(obj => {
let openTime = parseInt(serverCreateTimes[obj.serverId]);
return obj.groupId == groupId && getServerTypeByTime(openTime) == type;
}).map(obj => obj.serverId);
}
export async function getGVGInfoInGuild(guild: GuildType) {
let hasLeague = !!guild.leagueCode;
let serverId = guild.serverId;
let { configId, period, countdownTime } = getGVGPeriodData();
let type = await getGVGServerType(serverId);
return {
hasLeague,
configId, period, countdownTime,
type
}
}

View File

@@ -0,0 +1,228 @@
// 和gvg组建期相关的方法
import { GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, STATUS } from "../../consts";
import { GuildModel, GuildType } from "../../db/Guild";
import { GVGLeagueModel, GVGLeagueType, GVGLeagueUpdate } from "../../db/GVGLeague";
import { GVGLeagueApplyModel, GVGLeagueApplyType } from "../../db/GVGLeagueApply";
import { GVGLeaguePrepareModel, GVGLeaguePrepareType } from "../../db/GVGLeaguePrepare";
import { RoleType } from "../../db/Role";
import { UserGuildModel } from "../../db/UserGuild";
import { LeagueGuildInfo, LeagueListInfo } from "../../domain/gvgField/returnData";
import { GVG } from "../../pubUtils/dicParam";
import { getZeroPointD } from "../../pubUtils/timeUtil";
import { resResult } from "../../pubUtils/util";
import { sendMessageToUserWithSuc } from "../pushService";
import { getCurPeriod, getGVGConfig, getGVGPeriodData, getGVGServerType } from "./gvgService";
/**
* 自动创建联军
* @param guildCode 创建联军的那个军团
* @returns GVGLeagueType
*/
export async function autoCreateLeague(guildCode: string) {
let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
if(!guild || guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return;
let period = getCurPeriod();
if(period == GVG_PERIOD.PREPARE || period == GVG_PERIOD.BATTLE) {
return await createLeague(guild, {});
}
}
/**
* 创建联军
* @param guild 创建联军的那个军团
* @param params 联军的一些初始数据
* @returns
*/
export async function createLeague(guild: GuildType, params: GVGLeagueUpdate) {
let serverType = await getGVGServerType(guild.serverId);
params.type = serverType;
params.serverId = guild.serverId;
const league = await GVGLeagueModel.createLeague(guild, params);
await GuildModel.joinLeague(guild.code, league.leagueCode);
return league;
}
/**
* 获取在联军中的职位
* @param league
* @param roleId
* @returns
*/
export function getMyAuth(league: GVGLeagueType, roleId: string) {
let members = league.members;
let member = members.find(cur => cur.roleId == roleId);
return member?.auth?? LEAGUE_AUTH.MEMBER;
}
/**
* 加入联军的当天如果是在准备期,这天不能去参加内政
* @param roleId
* @returns
*/
export async function checkCanPrepare(roleId: string) {
let userGuild = await UserGuildModel.getMyGuild(roleId, 'createdAt');
let today = getZeroPointD();
return userGuild.createdAt < today;
}
/**
* 是否可以选择职能,如果选择的人数超过了就不可以选
* @param myJob
* @param league
* @returns
*/
export function checkCanChooseJob(myJob: number, league: GVGLeaguePrepareType) {
if(myJob > 0) return false;
if(!league) return false;
let { producerCnt, fighterCnt, maxMemberCnt } = league;
return producerCnt + fighterCnt <= maxMemberCnt;
}
/**
* 获取申请数据
* @param apply 本条申请原数据
* @param serverNames 全服务器的名字from redis
* @param invitations 本联军向其他军团发出的邀请
* @returns
*/
export function getLeagueApplyData(apply: GVGLeagueApplyType, serverNames: any, invitations: GVGLeagueApplyType[] ) {
let data = new LeagueGuildInfo(<GuildType>apply.guild, serverNames);
let hasInvited = !!invitations.find(cur => cur.guildCode == apply.guildCode);
data.setHasInvited(hasInvited);
return data;
}
/**
* 获取邀请数据
* @param invite 本条邀请原数据
* @param serverNames 全服务器的名字from redis
* @param applies 本军团向其他联军发出的申请
* @returns
*/
export function getLeagueInviteData(invite: GVGLeagueApplyType, serverNames: any, applies: GVGLeagueApplyType[]) {
let data = new LeagueListInfo(<GVGLeagueType>invite.league, serverNames);
let hasApply = !!applies.find(cur => cur.leagueCode == invite.guildCode);
data.setHasApply(hasApply);
return data;
}
/**
* 联军加入军团
* @param myLeague
* @param targetGuildCode
* @returns
*/
export async function joinGuildToLeague(league: GVGLeagueType, targetGuildCode: string) {
const hasApply = await GVGLeagueApplyModel.checkApply(league.leagueCode, targetGuildCode, GVG_APPLY_TYPE.ALL);
if(!hasApply) {
return resResult(STATUS.GUILD_NOT_APPLY);
}
if(league.guildCnt >= GVG.GVG_LEAGUE_COMPOSE) {
return resResult(STATUS.LEAGUE_IS_GUILD_MAX);
}
let hisLeague = await GVGLeagueModel.findLeagueByGuild(targetGuildCode);
if(hisLeague) {
await GVGLeagueApplyModel.deleteApply(targetGuildCode, league.leagueCode);
return resResult(STATUS.TARGET_GUILD_HAS_LEAGUE);
}
const targetGuild = await GuildModel.findByCode(targetGuildCode, null, '+members');
if(!targetGuild) return resResult(STATUS.TARGET_GUILD_NOT_FOUND);
if(targetGuild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH);
league = await GVGLeagueModel.joinGuild(league.leagueCode, targetGuild);
await GuildModel.joinLeague(targetGuildCode, league.leagueCode);
return resResult(STATUS.SUCCESS, league);
}
/**
* 检查是否可以进行组建联军等操作
* @param serverId
* @param serverType
* @returns
*/
export async function checkCanManage(serverId: number, serverType?: number) {
if(!serverType) serverType = await getGVGServerType(serverId);
if(serverType != GVG_SERVER_TYPE.MULTI) return resResult(STATUS.GVG_TEAM_SERVER_TYPE_ERR);
let { period } = getGVGPeriodData();
if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD);
return resResult(STATUS.SUCCESS);
}
/**
* 一些操作只能由军团的团长才能操作
* @param guildCode
* @param roleId
* @param guild
* @returns
*/
export async function checkGuildLeader(guildCode: string, roleId: string, guild?: GuildType) {
if(!guild) guild = await GuildModel.findByCode(guildCode, null, '+members +serverId');
if(!guild) return resResult(STATUS.GVG_HAS_NO_AUTH);
if(guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH);
const userGuild = await UserGuildModel.getMyGuild(roleId, 'auth');
if(!userGuild || userGuild.auth != GUILD_AUTH.LEADER) return resResult(STATUS.GVG_HAS_NO_AUTH);
return resResult(STATUS.SUCCESS);
}
/**
* 检查联军的操作
* @param roleId
* @param myLeague
* @param type
* @returns
*/
export async function checkLeagueAuth(roleId: string, myLeague: GVGLeagueType, type: LEAGUE_MANAGE_TYPE) {
const auth = getMyAuth(myLeague, roleId);
const needAuth = getAuthFromManageType(type);
return needAuth.indexOf(auth) > -1
}
function getAuthFromManageType(type: LEAGUE_MANAGE_TYPE) {
switch(type) {
case LEAGUE_MANAGE_TYPE.HANDLE_APPLY:
case LEAGUE_MANAGE_TYPE.INVITE:
case LEAGUE_MANAGE_TYPE.KICK:
case LEAGUE_MANAGE_TYPE.DISSMISS:
case LEAGUE_MANAGE_TYPE.ABDICATE:
return [LEAGUE_AUTH.LEADER];
case LEAGUE_MANAGE_TYPE.QUIT:
case LEAGUE_MANAGE_TYPE.BE_ABDICATED:
return [LEAGUE_AUTH.SUB_LEADER];
case LEAGUE_MANAGE_TYPE.SET_INFO:
return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER];
}
}
export async function memberJoinGuildToLeague(guild: GuildType, role: RoleType) {
if(!guild.leagueCode) return;
let league = await GVGLeagueModel.joinMember(guild.leagueCode, role.roleId, role.ce);
// TODO redis联军更新
console.log(league);
}
export async function memberQuitGuildToLeague(guild: GuildType, role: RoleType) {
if(!guild.leagueCode) return;
let league = await GVGLeagueModel.quitMember(guild.leagueCode, role.roleId, role.ce);
// TODO redis联军更新
console.log(league);
}
export async function guildDismissToLeague(guild: GuildType) {
if(!guild.leagueCode) return;
let league = await GVGLeagueModel.quitGuild(guild.leagueCode, guild);
// TODO redis联军更新
console.log(league);
}
export async function guildAbdicateToLeague(guild: GuildType, fromRoleId: string, toRole: RoleType) {
if(!guild.leagueCode) return;
let league = await GVGLeagueModel.abdicateGuild(guild.leagueCode, fromRoleId, toRole.roleId, toRole._id);
// TODO redis联军更新
console.log(league);
}

View File

@@ -20,6 +20,7 @@ import { sendMessageToUserWithSuc } from './pushService';
import { SkinType } from '../db/Skin';
import { LadderMatchModel } from '../db/LadderMatch';
import { ArtifactModelType } from '../db/Artifact';
import { GVGLeagueModel } from '../db/GVGLeague';
interface Param {
isInitRole?: boolean,
@@ -454,6 +455,7 @@ export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serve
roleCe = await RoleCeModel.updateRoleCe(roleId, roleCeUpdate);
let role = await RoleModel.incRoleInfo(roleId, { ...roleIncUpdate, ce: roleInc }, { ...roleUpdate, topLineup, topLineupCe });
let guild = await GuildModel.updateCe(roleId, roleInc); // 公会更新战力
let league = await GVGLeagueModel.updateCe(roleId, roleInc); // 联军更新战力
saveCeChangeLog(role, roleInc, role.ce, type, ceChangeTxt);
updateRank(roleId, serverId, topLineupCe, role, pushHeros, guild);
@@ -461,6 +463,9 @@ export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serve
if(hasTopCeChange) await updateRoleOnlineInfo(roleId, { topLineupCe });
if(guild) {
await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]);
}
if(league) { // TODO 联军排行榜需要更新数据
}
return { heroes, curRole: role }
}

View File

@@ -513,7 +513,7 @@ async function setServerList() {
await redisClient().delAsync(REDIS_KEY.SERVER);
await redisClient().delAsync(REDIS_KEY.SERVER_OPEN_TIME);
for(let { id, name, openTime, env } of serverList) {
for(let { id, serverId, name, openTime, env } of serverList) {
if(env == pinus.app.get('env')) {
// console.log(roleId);
await redisClient().hsetAsync(REDIS_KEY.SERVER, `${id}`, `${name}`);
@@ -536,7 +536,7 @@ export async function getAllServers() {
}
export async function getAllServerName() {
let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER);
let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER);
return servers;
}
@@ -550,6 +550,11 @@ export async function getServerCreateTime(serverId: number) {
return parseInt(time);
}
export async function getAllServerCreateTime() {
let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER_OPEN_TIME);
return servers;
}
export function redisClient() {
const client: Redis.RedisClient = pinus.app.get('redis');
return client;

View File

@@ -42,6 +42,8 @@ import { LadderMatchModel } from '../db/LadderMatch';
import { getGroupShopTimers, refundGroupShop, setGroupShopToSetSum } from './activity/groupShopService';
import { HiddenDataModel, HiddenDataModelType } from '../db/HiddenData';
import { setHiddenData, setHiddenDataToMemory } from './dataService';
import { GVGConfigModel } from '../db/GVGConfig';
import { createNewGVGConfig, initLeaguePrepare, setGVGConfigToRemote } from './gvg/gvgService';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
@@ -106,6 +108,9 @@ export async function init() {
// 隐藏数据定时器
initHiddenDataSchedule(true);
// gvg每周日
initGVGConfigSchedule();
}
// 每日刷新
@@ -889,4 +894,26 @@ export async function initHiddenDataSchedule(isInit: boolean, data?: HiddenDataM
});
}
}
// —————————————— 配表兼容 end —————————————— //
// —————————————— 配表兼容 end —————————————— //
// —————————————— gvg start —————————————— //
export async function initGVGConfigSchedule() {
let config = await GVGConfigModel.findConfig();
if(!config) {
config = await createNewGVGConfig();
}
setGVGConfigToRemote(config);
if(nowSeconds() > config.scheduleTime) {
config = await createNewGVGConfig();
} else {
scheduleJob(`gvgConfig`, config.scheduleTime * 1000, createNewGVGConfig);
}
if(nowSeconds() > config.prepareTime) {
initLeaguePrepare();
} else {
scheduleJob(`gvgPrepare`, config.prepareTime * 1000, initLeaguePrepare);
}
}
// —————————————— gvg end —————————————— //

View File

@@ -215,4 +215,16 @@ export default class GameController extends Controller {
ctx.body = await ctx.service.game.getExistHiddenData(type);
return
}
public async getGVGServerGroup() {
const { ctx } = this;
ctx.body = await ctx.service.game.getGVGServerGroup();
return
}
public async getGVGConfig() {
const { ctx } = this;
ctx.body = await ctx.service.game.getGVGConfig();
return
}
}

View File

@@ -60,6 +60,8 @@ export default (app: Application) => {
router.post('/api/game/updatechannel', controller.game.updateChannel);
router.post('/api/game/gethiddendata', controller.game.getHiddenData);
router.post('/api/game/getexisthiddendata', controller.game.getExistHiddenData);
router.post('/api/game/getgvgservergroup', controller.game.getGVGServerGroup);
router.post('/api/game/getgvgconfig', controller.game.getGVGConfig);
router.post('/api/dic/getdicgoods', tokenParser, controller.game.getDicGoods);
router.post('/api/dic/getdichero', tokenParser, controller.game.getDicHero);

View File

@@ -23,6 +23,8 @@ import { ChannelInfoModel } from '@db/ChannelInfo';
import { PVPConfigModel } from '@db/PvpConfig';
import { HiddenDataByIdModel } from '@db/HiddenDataById';
import { isNumber } from 'util';
import { GVGServerGroupModel } from '@db/GVGServerGroup';
import { GVGConfigModel } from '@db/GVGConfig';
/**
* Test Service
@@ -347,4 +349,31 @@ export default class Game extends Service {
ids: existIds
});
}
public async getGVGServerGroup() {
const { ctx } = this;
const serverlists = await ServerlistModel.findByEnv(this.app.config.realEnv);
const currentTypes = await GVGServerGroupModel.findByTime(nowSeconds());
const nextTypes = await GVGServerGroupModel.findByTime(nowSeconds() + 7 * 86400);
const servers = serverlists.map(server => {
let current = currentTypes.find(obj => obj.serverId == server.id);
let next = nextTypes.find(obj => obj.serverId == server.id);
let dic = gameData.serverNames.get(server.id);
return { id: server.id, serverId: server.serverId, name: server.name, current: current?.groupId|| dic.groupId, next: next?.groupId|| current?.groupId || dic.groupId, env: this.app.config.realEnv }
});
return ctx.service.utils.resResult(STATUS.SUCCESS, {
list: servers
});
}
public async getGVGConfig() {
const { ctx } = this;
const gvgconfig = await GVGConfigModel.findConfig();
return ctx.service.utils.resResult(STATUS.SUCCESS, {
list: gvgconfig?[{...gvgconfig, env: this.app.config.realEnv }]: []
});
}
}

View File

@@ -31,5 +31,6 @@ declare module 'egg' {
jsonp?: EggPluginItem;
view?: EggPluginItem;
cors?: EggPluginItem;
xtransit?: EggPluginItem;
}
}

View File

@@ -170,4 +170,8 @@ export const PUSH_ROUTE = {
LADDER_RANK_UPDATE: 'onLadderRankUpdate',
GROUP_SHOP_UPDATE: 'onGroupShopUpdate',
HIDDEN_DATA: 'onHiddenData',
LEAGUE_APPLY: 'onLeagueApply', // 当联军收到军团申请
LEAGUE_KICK: 'onKickedByLeague', // 当被踢出
LEAGUE_DISSMISS: 'onLeagueDismiss', // 当联军解散
LEAGUE_ABDICATE: 'onLeagueAbdicate', // 当被转让盟主
}

View File

@@ -0,0 +1,34 @@
export enum GVG_PERIOD {
TEAM = 1, // 组建期
PREPARE = 2, // 备战期
BATTLE = 3, // 战斗器
}
export enum LEAGUE_AUTH {
LEADER = 1, // 盟主
SUB_LEADER = 2, // 副盟主
MEMBER = 3, // 平民
}
export enum GVG_SERVER_TYPE {
NO = 0, // 刚开服根本不能参加的时候
SINGLE = 1, // 单服
MULTI = 2, // 跨服
}
export enum GVG_APPLY_TYPE {
ALL = 0,
APPLY = 1, // 军团向联军申请
INVITE = 2, // 联军向军团邀请
}
export enum LEAGUE_MANAGE_TYPE {
HANDLE_APPLY = 1, // 处理申请
INVITE = 2, // 邀请军团
KICK = 3, // 踢出军团
QUIT = 4, // 主动退出
DISSMISS = 5, // 解散联军
ABDICATE = 6, // 转让
BE_ABDICATED = 7, // 被转让
SET_INFO = 8, // 设置信息
}

View File

@@ -54,6 +54,7 @@ export const COUNTER = {
RACE_ACTIVITY: { name: 'raceAct', def: 1 },
HIDDEN_DATA: { name: 'hiddendata', def: 1 },
ARTIFACT_ID: { name: 'artid', def: 1 },
GVG_CONFIG: { name: 'gvg', def: 1 },
};
export const DEFAULT_HEROES = [19, 53,];
@@ -565,6 +566,7 @@ export const FILENAME = {
DIC_ARTIFACT_QUALITY_PLAN: 'dic_zyz_artifactQualityPlan',
DIC_ARTIFACT_QUALITY: 'dic_zyz_artifactQuality',
DIC_ARTIFACT_SEID: 'dic_zyz_artifactSeid',
DIC_GVG_PERIOD: 'dic_zyz_GVGPeriod',
}
export const WAR_RELATE_TABLES = [

View File

@@ -10,5 +10,6 @@ export * from './constModules/chatConst';
export * from './constModules/httpConst';
export * from './constModules/auctionConst';
export * from './constModules/mailConst';
export * from './constModules/gvgConst';
export * from './statusCode';
export * from './dataName';

View File

@@ -287,6 +287,25 @@ export const STATUS = {
LADDER_RANK_ERR: { code: 21208, simStr: '不可连战比排名自己高的玩家' },
LADDER_SWEEP_TIMES_OVER: { code: 21209, simStr: '连战次数过多' },
// GVG相关
GVG_HAS_NO_AUTH: { code: 21300, simStr: '您的权限不足' },
GVG_NOT_TEAM_PERIOD: { code: 21301, simStr: '您只能在组建期创建联军' },
GVG_TEAM_SERVER_TYPE_ERR: { code: 21302, simStr: '单服玩法不需要联军' },
GVG_LEAGUE_HAS_EXIST: { code: 21303, simStr: '联军已存在' },
GVG_NO_SERVER_TYPE: { code: 21304, simStr: '服务器开服一周后开放玩法' },
LEAGUE_IS_GUILD_MAX: { code: 21305, simStr: '该联军军团数已满' },
GVG_LEAGUE_NOT_EXIST: { code: 21306, simStr: '联军不存在' },
TARGET_GUILD_HAS_LEAGUE: { code: 21307, simStr: '对方已加入其他联军' },
TARGET_GUILD_NOT_FOUND: { code: 21308, simStr: '未找到该军团' },
GUILD_NOT_APPLY: { code: 21309, simStr: '对方军团未申请' },
GUILD_LV_NOT_ENOUGH: { code: 31310, simStr: '军团等级不足' },
GVG_CANNOUT_KICK_SELF_GUILD: { code: 31311, simStr: '不可踢走自己的军团' },
GUILD_HAS_QUIT: { code: 31312, simStr: '军团已经退出联军了' },
GVG_CANNOT_QUIT_OTHER_GUILD: { code: 31313, simStr: '只能主动退出自己的军团' },
LEAGUE_CODE_ERR: { code: 31314, simStr: '不能解散其他联军' },
GVG_HE_HAS_NO_AUTH: { code: 21300, simStr: '对方权限不足' },
LEAGUE_NAME_DUP: { code: 21301, simStr: '联军名重复' },
// 通用 30000 - 30099
DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' },
ROLE_MATERIAL_NOT_ENOUGH: { code: 30001, simStr: '材料数量不足' },
@@ -572,6 +591,7 @@ export const STATUS = {
GM_HIDDEN_CANNOT_INIT: { code: 60030, simStr: '已初始化过' },
GM_ACTIVITY_TIME_ERR: { code: 60031, simStr: '时间不可有重叠' },
GM_USER_TYPE_ERR: { code: 60032, simStr: '您不可使用账号密码登录,请从专属后台点击链接进入' },
GM_GVG_TIME_ERR: { code: 60033, simStr: '时间配置错误' },
// 支付相关状态 70000 - 79999
NO_PRODUCT_ID: { code: 70001, simStr: '无效商品' },
NO_PAY_TYPE: { code: 70002, simStr: '无效支付类型' },

48
shared/db/GVGConfig.ts Normal file
View File

@@ -0,0 +1,48 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
@index({ configId: -1 })
export default class GVGConfig extends BaseModel {
@prop({ required: true, default: 1 })
configId: number; // 配置唯一id
@prop({ required: true })
teamTime: number; // 组建期开始
@prop({ required: true })
prepareTime: number; // 准备期开始
@prop({ required: true })
battleTime: number; // 激战期开始
@prop({ required: true })
scheduleTime: number; // 下次定时任务时间
public static async createNewConfig(teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number) {
const configId = await CounterModel.getNewCounter(COUNTER.GVG_CONFIG);
const result: GVGConfigType = await GVGConfigModel.findOneAndUpdate({ configId }, { $set: { teamTime, prepareTime, battleTime, scheduleTime } }, { upsert: true, new: true }).lean();
return result;
}
public static async findConfig() {
let configId = await CounterModel.getCounter(COUNTER.GVG_CONFIG);
const result: GVGConfigType = await GVGConfigModel.findOne({ configId }, { _id: 0 }).lean();
return result;
}
public static async updateConfig(configId: number, teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number) {
const result: GVGConfigType = await GVGConfigModel.findOneAndUpdate({ configId }, { $set: { teamTime, prepareTime, battleTime, scheduleTime } }, { new: true }).lean();
return result;
}
}
export const GVGConfigModel = getModelForClass(GVGConfig);
export interface GVGConfigType extends Pick<DocumentType<GVGConfig>, keyof GVGConfig> {
id: number;
};
export type GVGConfigUpdate = Partial<GVGConfigType>; // 将所有字段变成可选项

195
shared/db/GVGLeague.ts Normal file
View File

@@ -0,0 +1,195 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose';
import Role, { RoleType } from '../db/Role';
import { genCode } from '../pubUtils/util';
import { GuildType } from './Guild';
import { LEAGUE_AUTH } from '../consts';
class Member {
@prop({ required: true })
roleId: string;
@prop({ required: true })
auth: number;
}
@index({ leagueCode: 1, status: 1 })
@index({ guildCodes: 1, status: 1 })
@index({ 'members.roleId': 1, status: 1 })
export default class GVGLeague extends BaseModel {
@prop({ required: true })
leagueCode: string; // 唯一id
@prop({ required: true, type: String })
guildCodes: string[]; // 包含军团
@prop({ required: true, ref: () => Role, type: mongoose.Schema.Types.ObjectId })
leader: Ref<Role>;
@prop({ required: true, default: '' })
name: string; // 名称
@prop({ required: true, default: 1 })
icon: number; // 图标
@prop({ required: true, default: '' })
notice: string; // 公告
@prop({ required: true, default: 0 })
guildCnt: number; // 军团数量
@prop({ required: true, default: 0 })
memberCnt: number; // 玩家人数
@prop({ required: true, default: 0 })
leagueCe: number; // 联军总战力
@prop({ required: true, default: false })
isAuto: boolean; // 是否是自动创建的
@prop({ required: true, default: 1 })
status: number; // 1-健在 0-解散
@prop({ required: true, default: 1 })
type: number; // 1-单服 2-跨服
@prop({ required: true, default: 1 })
serverId: number; // 服务器id
@prop({ required: true, default: [], type: Member, _id: false })
members: Member[];
public static async checkName(name: string) {
const result = await GVGLeagueModel.exists({ name, status: 1 });
return result;
}
public static async createLeague(guild: GuildType, params: GVGLeagueUpdate) {
const { code, name, memberCnt, leader, guildCe, members } = guild;
const doc = new GVGLeagueModel();
const leagueCode = genCode(6);
let _leader = <RoleType>leader;
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.LEADER: LEAGUE_AUTH.MEMBER }));
const update = Object.assign(doc.toJSON(), { guildCodes: [code], name: `${name}联军`, guildCnt: 1, memberCnt, isAuto: true, leagueCe: guildCe, leader: _leader?._id, members: _members, leagueCode }, params);
delete update._id;
const result: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ guildCodes: code, status: 1 }, { $setOnInsert: update }, { upsert: true, new: true })
.select({ _id: 0, __v: 0, createdAt: 0, updatedAt: 0 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.lean();
return result;
}
public static async findLeagueByGuild(guildCode: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOne({ guildCodes: guildCode, status: 1 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.lean();
return league
}
public static async findByCondition(type: number, serverIds: number[], page: number, name: string) {
let query = {
status: 1, type, serverId: { $in: serverIds }
};
if(name) {
query['name'] = { $regex: new RegExp(name, 'i') };
}
const league: GVGLeagueType[] = await GVGLeagueModel.find(query)
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.skip((page - 1) * 30).limit(30)
.lean();
return league
}
public static async findByCode(leagueCode: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOne({ leagueCode, status: 1 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.lean();
return league
}
public static async findByCodes(leagueCodes: string[]) {
const leagues: GVGLeagueType[] = await GVGLeagueModel.find({ leagueCode: { $in: leagueCodes }, status: 1 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.lean();
return leagues
}
public static async joinGuild(leagueCode: string, guild: GuildType) {
const { code, memberCnt, leader, guildCe, members } = guild;
let _leader = <RoleType>leader;
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.SUB_LEADER: LEAGUE_AUTH.MEMBER }));
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
{ $push: { guildCodes: code, members: { $each: _members } }, $inc: { guildCnt: 1, memberCnt: memberCnt, leagueCe: guildCe }
}, { new: true }).lean();
return league
}
public static async findAllLeague() {
const leagues: { leagueCode: string, memberCnt: number }[] = await GVGLeagueModel.aggregate([
{ $match: { status: 1 } },
{ $project: { leagueCode: 1, memberCnt: 1 } }
]);
return leagues;
}
public static async quitGuild(leagueCode: string, guild: GuildType) {
const { code, memberCnt, members, guildCe } = guild;
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
{ $pull: { guildCodes: code, members: { roleId: { $in: members } } }, $inc: { guildCnt: -1, memberCnt: -memberCnt, leagueCe: -guildCe }
}, { new: true }).lean();
return league
}
public static async dismiss(leagueCode: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $set: { status: 0 }}, { new: true }).lean();
return league
}
public static async abdicate(leagueCode: string, fromRoleId: string, toRoleId: string, leader: string) {
let league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': fromRoleId }, { $set: { 'members.$.auth': LEAGUE_AUTH.SUB_LEADER }}, { new: true }).lean();
league = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': toRoleId }, { $set: { 'members.$.auth': LEAGUE_AUTH.LEADER, leader }}, { new: true }).lean();
return league
}
public static async setInfo(leagueCode: string, name: string, notice: string, icon: number) {
let updateInfo: GVGLeagueUpdate = {};
if(name != undefined) updateInfo.name = name;
if(notice != undefined) updateInfo.notice = notice;
if(icon != undefined) updateInfo.icon = icon;
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $set: updateInfo }, { new: true }).lean();
return league;
}
public static async updateCe(roleId: string, incCe: number) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ 'members.roleId': roleId, status: 1 }, { $inc: { leagueCe: incCe } }, { new: true }).lean();
return league;
}
public static async joinMember(leagueCode: string, roleId: string, ce: number) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $push: { members: { roleId, auth: LEAGUE_AUTH.MEMBER } }, $inc: { memberCnt: 1, leagueCe: ce } }, { new: true }).lean();
return league;
}
public static async quitMember(leagueCode: string, roleId: string, ce: number) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $pull: { members: { roleId } }, $inc: { memberCnt: -1, leagueCe: -ce } }, { new: true }).lean();
return league;
}
public static async abdicateGuild(leagueCode: string, fromRoleId: string, toRoleId: string, leader: string) {
let league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': fromRoleId }, { $set: { 'members.$.auth': LEAGUE_AUTH.MEMBER }}).lean();
const member = league.members.find(cur => cur.roleId == fromRoleId);
const updateInfo = { 'members.$.auth': member?.auth };
if(member?.auth == LEAGUE_AUTH.LEADER) updateInfo['leader'] = leader;
league = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': toRoleId }, { $set: updateInfo }, { new: true }).lean();
return league
}
}
export const GVGLeagueModel = getModelForClass(GVGLeague);
export interface GVGLeagueType extends Pick<DocumentType<GVGLeague>, keyof GVGLeague> {
id: number;
};
export type GVGLeagueUpdate = Partial<GVGLeagueType>; // 将所有字段变成可选项

104
shared/db/GVGLeagueApply.ts Normal file
View File

@@ -0,0 +1,104 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index, Ref } from '@typegoose/typegoose';
import GVGLeague, { GVGLeagueType } from './GVGLeague';
import Guild, { GuildType } from './Guild';
import { GVG_APPLY_TYPE } from '../consts';
@index({ leagueCode: 1, guildCode: 1, type: 1 })
export default class GVGLeagueApply extends BaseModel {
@prop({ required: true })
leagueCode: string; // 发起的联军 or 收到申请的联军
@prop({ required: true })
league: Ref<GVGLeague>;
@prop({ required: true })
guildCode: string; // 受邀的军团 or 发出申请的联军
@prop({ required: true })
guild: Ref<Guild>;
@prop({ required: true })
type: number; // 类型 1-邀请 2-申请
public static async findApplyFromGuild(guildCode: string) {
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ guildCode, type: GVG_APPLY_TYPE.APPLY }).lean();
return result;
}
public static async checkApply(leagueCode: string, guildCode: string, type: GVG_APPLY_TYPE) {
console.log('####', leagueCode, guildCode, type)
const result = await GVGLeagueApplyModel.exists({ guildCode, leagueCode,
type: type == GVG_APPLY_TYPE.ALL? { $in: [GVG_APPLY_TYPE.APPLY, GVG_APPLY_TYPE.INVITE] }: type
});
return result;
}
public static async createApply(league: GVGLeagueType, guild: GuildType, type: number) {
const result: GVGLeagueApplyType = await GVGLeagueApplyModel.findOneAndUpdate({ leagueCode: league.leagueCode, guildCode: guild.code, type }, { $set: { league: league._id, guild: guild._id, }}, { new: true, upsert: true })
.lean();
return result;
}
public static async findApplyFromLeague(leagueCode: string) {
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ leagueCode, type: GVG_APPLY_TYPE.APPLY })
.select({ _id: 0, guild: 1, guildCode: 1 })
.populate({
path: 'guild',
select: 'code icon name lv memberCnt leader guildCe +serverId',
model: 'Guild',
populate: {
path: 'leader',
select: 'roleName',
model: 'Role'
}
})
.lean();
return result;
}
public static async findInviteFromLeague(leagueCode: string) {
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ leagueCode, type: GVG_APPLY_TYPE.INVITE }).lean();
return result;
}
public static async findInviteFromGuild(guildCode: string) {
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ guildCode, type: GVG_APPLY_TYPE.INVITE })
.select({ _id: 0, guild: 1, guildCode: 1 })
.populate({
path: 'league',
// select: 'code icon name lv memberCnt leader guildCe +serverId',
model: 'GVGLeague',
populate: {
path: 'leader',
select: 'roleName',
model: 'Role'
}
})
.lean();
return result;
}
public static async deleteApply(guildCode: string, leagueCode: string) {
const n = await GVGLeagueApplyModel.deleteMany({ guildCode, leagueCode, type: GVG_APPLY_TYPE.APPLY });
return n;
}
public static async deleteAllGuildApply(guildCode: string) {
const n = await GVGLeagueApplyModel.deleteMany({ guildCode, type: GVG_APPLY_TYPE.APPLY });
return n;
}
public static async deleteInvite(guildCode: string, leagueCode: string) {
const n = await GVGLeagueApplyModel.deleteMany({ guildCode, leagueCode, type: GVG_APPLY_TYPE.INVITE });
return n;
}
}
export const GVGLeagueApplyModel = getModelForClass(GVGLeagueApply);
export interface GVGLeagueApplyType extends Pick<DocumentType<GVGLeagueApply>, keyof GVGLeagueApply> {
id: number;
};
export type GVGLeagueApplyUpdate = Partial<GVGLeagueApplyType>; // 将所有字段变成可选项

View File

@@ -0,0 +1,82 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
class Tech {
@prop({ required: true, default: 0 })
id: number;
@prop({ required: true, default: 0 })
progress: number; // 贡献
@prop({ required: true, default: 0 })
status: number; // 0-已解锁 1-已激活
}
class DonateRec {
@prop({ required: true, default: 0 })
roleId: string;
@prop({ required: true, default: 0 })
time: number;
@prop({ required: true, default: 0 })
count: number;
}
class Resource {
@prop({ required: true, default: 0 })
food: number; // 粮食
@prop({ required: true, default: 0 })
mineral: number; // 矿物
@prop({ required: true, default: 0 })
wood: number; // 木堆
}
@index({ leagueCode: 1, configId: 1 })
export default class GVGLeaguePrepare extends BaseModel {
@prop({ required: true })
configId: number; // 赛期配置id
@prop({ required: true })
leagueCode: string; // 联军
@prop({ required: true, default: 1 })
lv: number; // 等级
@prop({ required: true, default: 0 })
maxMemberCnt: number; // 进入备战期初始玩家人数
@prop({ required: true, default: 0 })
producerCnt: number; // 选择内政人数
@prop({ required: true, default: 0 })
fighterCnt: number; // 选择外政人数
@prop({ required: true, default: [], type: Tech, _id: false })
tech: Tech[]; // 千机阁
@prop({ required: true, default: [], type: DonateRec, _id: false })
donateRec: DonateRec[]; // 捐献记录
@prop({ required: true, default: {food: 0, mineral: 0, wood: 0}, type: Resource, _id: false })
resources: Resource
public static async initData(configId: number, leagueCode: string, maxMemberCnt: number) {
const doc = new GVGLeaguePrepareModel();
const update = Object.assign(doc.toJSON(), { maxMemberCnt });
delete update._id;
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({ configId, leagueCode }, { $setOnInsert: update }, { upsert: true, new: true })
.select({ _id: 0, __v: 0, createdAt: 0, updatedAt: 0 }).lean();
return result;
}
public static async findByLeague(configId: number, leagueCode: string) {
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOne({ configId, leagueCode }).lean();
return result;
}
}
export const GVGLeaguePrepareModel = getModelForClass(GVGLeaguePrepare);
export interface GVGLeaguePrepareType extends Pick<DocumentType<GVGLeaguePrepare>, keyof GVGLeaguePrepare> {
id: number;
};
export type GVGLeaguePrepareUpdate = Partial<GVGLeaguePrepareType>; // 将所有字段变成可选项

View File

@@ -0,0 +1,41 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
/**
* 服务器分战区
*/
@index({ time: -1, serverId: -1 })
export default class GVGServerGroup extends BaseModel {
@prop({ required: true, default: 1 })
serverId: number; // 服务器id
@prop({ required: true, default: 1 })
groupId: number; // 战区id
@prop({ required: true, default: 0 })
time: number; // 生效时间
public static async findByTime(time: number) {
const serverGroup: { serverId: number, groupId: number }[] = await GVGServerGroupModel.aggregate([
{ $match: { time: { $lte: time } } },
{ $sort: { time: -1 } },
{ $group: { _id: "$id", serverId: { $first: "$serverId" }, groupId: { $first: "$groupId" }, time: { $first: "$time" }} },
{ $sort: { _id: -1 } },
{ $project: { _id: 0, id: "$_id", serverId: "$serverId", groupId: "$groupId", time: "$time" } }
]);
return serverGroup;
}
public static async updateByServerId(serverId: number, groupId: number, time: number) {
const result: GVGServerGroupType = await GVGServerGroupModel.findOneAndUpdate({ serverId, time }, { $set: { groupId } }, { new: true, upsert: true }).lean();
return result
}
}
export let GVGServerGroupModel = getModelForClass(GVGServerGroup);
export interface GVGServerGroupType extends Pick<DocumentType<GVGServerGroup>, keyof GVGServerGroup> {
id: number;
};
export type GVGServerGroupUpdate = Partial<GVGServerGroupType>; // 将所有字段变成可选项

81
shared/db/GVGUserData.ts Normal file
View File

@@ -0,0 +1,81 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
class ActiveRec {
@prop({ required: true, default: 1 })
id: number; // 1-内政令消耗 2-征战令消耗 3-科技树捐献
@prop({ required: true, default: 0 })
count: number;
@prop({ required: true, default: 0 })
time: number;
}
class Box {
@prop({ required: true, default: 0 })
score: number; // 宝箱积分
@prop({ required: true, default: [], type: Number })
received: number[]; // 领取记录
}
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
export default class GVGUserData extends BaseModel {
@prop({ required: true })
roleId: string; // 玩家
@prop({ required: true })
configId: number; // 赛季信息
@prop({ required: true })
leagueCode: string; // 所属联军
@prop({ required: true, default: 0 })
job: number; // 职能 1-贤臣 2-猛将
// 备战期
@prop({ required: true, default: 0 })
active: number; // 活跃度
@prop({ required: true, default: 0, type: ActiveRec, _id: false })
activeRec: ActiveRec[]; // 活跃度记录
@prop({ required: true, default: 0 })
receivedLv: number; // 领取到的等级奖励
@prop({ required: true, default: 0 })
receiveCurrencyTime: number; // 领取内政令&征战令时间
@prop({ required: true, default: { score: 0, received: []}, type: Box, _id: false })
box: Box;
@prop({ required: true, default: 0 })
sendFightRewardTime: number; // 发送征战奖励的时间
// 激战期
@prop({ required: true, default: 0 })
battleStatus: number; // 1-被挑战中 0-可被挑战
@prop({ required: true, default: 0 })
area: number; // 所处区域 1-进攻北站 2-混战 3-据点 4-防守备战
@prop({ required: true, default: 0 })
protectTime: number; // 保护期
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
const result: GVGUserDataType = await GVGUserDataModel.findOneAndUpdate({ configId, leagueCode, roleId }, {}, { new: true, upsert: true}).lean();
return result;
}
public static async findByRoles(configId: number, leagueCode: string, roleIds: string[]) {
const result: GVGUserDataType[] = await GVGUserDataModel.find({ configId, leagueCode, roleId: { $in: roleIds } }).lean();
return result;
}
}
export const GVGUserDataModel = getModelForClass(GVGUserData);
export interface GVGUserDataType extends Pick<DocumentType<GVGUserData>, keyof GVGUserData> {
id: number;
};
export type GVGUserDataUpdate = Partial<GVGUserDataType>; // 将所有字段变成可选项

37
shared/db/GVGUserItem.ts Normal file
View File

@@ -0,0 +1,37 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
export default class GVGUserItem extends BaseModel {
@prop({ required: true })
roleId: string; // 玩家
@prop({ required: true })
leagueCode: string; // 联军id
@prop({ required: true })
configId: number; // 赛期
@prop({ required: true })
id: number; // 道具: 包括 种子、铲子、斧子
@prop({ required: true, default: 0 })
count: number; // 数量
@prop({ required: true, default: 0 })
expireTime: number;
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
const result: GVGUserItemType[] = await GVGUserItemModel.find({ configId, leagueCode, roleId, expireTime: { $gte: nowSeconds() } }, { _id: 0 }).lean();
return result;
}
}
export const GVGUserItemModel = getModelForClass(GVGUserItem);
export interface GVGUserItemType extends Pick<DocumentType<GVGUserItem>, keyof GVGUserItem> {
id: number;
};
export type GVGUserItemUpdate = Partial<GVGUserItemType>; // 将所有字段变成可选项

41
shared/db/GVGUserTask.ts Normal file
View File

@@ -0,0 +1,41 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
import { getZeroPointD } from '../pubUtils/timeUtil';
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
export default class GVGUserTask extends BaseModel {
@prop({ required: true, default: '' })
roleId: string; // 玩家
@prop({ required: true, default: '' })
leagueCode: string; // 联军id
@prop({ required: true, default: 0 })
configId: number; // 赛期
@prop({ required: true, default: 0 })
id: number; // 任务id
@prop({ required: true, default: 0 })
count: number; // 1-已达成
@prop({ required: true, default: 0 })
status: number; // 1-未领取 2-已领取
@prop({ required: true, default: 0 })
createTime: number; // 1-未领取 2-已领取
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
let today = getZeroPointD();
const result: GVGUserTaskType[] = await GVGUserTaskModel.find({ configId, leagueCode, roleId, createdAt: { $gte: today } }, { _id: 0, id: 1, count: 1, status: 1 }).lean();
return result;
}
}
export const GVGUserTaskModel = getModelForClass(GVGUserTask);
export interface GVGUserTaskType extends Pick<DocumentType<GVGUserTask>, keyof GVGUserTask> {
id: number;
};
export type GVGUserTaskUpdate = Partial<GVGUserTaskType>; // 将所有字段变成可选项

View File

@@ -111,6 +111,9 @@ export default class Guild extends BaseModel {
@prop({ required: true })
sdkMark: boolean; // 37sdk标记有问题
@prop({ required: true, default: '' })
leagueCode: string; // 参与联军
public static async createGuild(params: { guildCode: string, name: string, icon: number, notice: string }, role: RoleType, serverId: number) {
const doc = new GuildModel();
const update = Object.assign(doc.toJSON(), params, { leader: role._id, members: [role.roleId], guildCe: role.ce, serverId, lvUpdateTime: nowSeconds() });
@@ -175,7 +178,7 @@ export default class Guild extends BaseModel {
if(serverId) condition.serverId = serverId;
const result: GuildType = await GuildModel.findOne(condition)
.select(select)
.populate('leader', {roleId: 1, roleName: 1, frame: 1, head: 1, spine: 1, frames: 1, heads: 1, spines: 1, lv: 1, quitTime: 1, ce: 1, title: 1, _id: 0}, 'Role')
.populate('leader', {roleId: 1, roleName: 1, frame: 1, head: 1, spine: 1, frames: 1, heads: 1, spines: 1, lv: 1, quitTime: 1, ce: 1, title: 1}, 'Role')
.lean({ getters: true, virtuals: true });
return result;
}
@@ -315,6 +318,41 @@ export default class Guild extends BaseModel {
const result = await GuildModel.count(searchObj);
return result;
}
public static async joinLeague(guildCode: string, leagueCode: string) {
const result: GuildType = await GuildModel.findOneAndUpdate({ code: guildCode }, { $set: { leagueCode } }, { new: true }).lean();
return result
}
public static async findGuildsForGVG(page: number, name: string, serverIds: number[]) {
let query: any = { status: GUILD_STATUS.RUNNING, lv: { $gte: 3 }, leagueCode: '', serverId: { $in: serverIds } };
if(name) {
query['name'] = { $regex: new RegExp(name, 'i') }
}
const result: GuildType[] = await GuildModel.find(query)
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
.skip((page - 1) * 30).limit(30)
.lean();
return result;
}
public static async findByCodes(codes: string[]) {
const result: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, code: { $in: codes } })
.select('+serverId')
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
.lean();
return result;
}
public static async quitFromLeague(guildCode: string, leagueCode: string, select = null) {
const result: GuildType = await GuildModel.findOneAndUpdate({ code: guildCode, leagueCode }, { $set: { leagueCode: '' } }, { new: true }).select(select).lean();
return result;
}
public static async dissmissLeague(leagueCode: string) {
const result: GuildType = await GuildModel.findOneAndUpdate({ leagueCode }, { $set: { leagueCode: '' }}).lean();
return result;
}
}
export const GuildModel = getModelForClass(Guild);

View File

@@ -0,0 +1,224 @@
import { RoleType } from "../../db/Role";
import { GVGLeagueType } from "../../db/GVGLeague";
import { GVGLeaguePrepareType } from "../../db/GVGLeaguePrepare";
import { GVGUserDataType } from "../../db/GVGUserData";
import { GuildType } from "../../db/Guild";
class LeagueLeaderInfo {
name: string; // 盟主名
serverId: number; // 盟主所处小区
serverName: number; // 盟主所处小区名
constructor(leader: RoleType, serverNames: any) {
this.name = leader.roleName;
this.serverId = leader.serverId;
this.serverName = serverNames[this.serverId];
}
}
class GVGItem {
id: number;
count: number;
expireTime: number; // 过期时间
}
class LeaguePlayerData {
auth: number = 3; // 我的权限 1-盟主 2-副盟主 3-平民
job: number = 0; // 我的职能1-贤臣 2-猛将 0-未选择
canPrepare: boolean = false; // 是否可以使用整备期模块,组建期过后加入的玩家,当天的整备模块不可参与
canChooseJob: boolean = true; // 是否可以选择职能,团内选择职业的人数达到最大人数了,已经不可再选职位了
items: GVGItem[] = []; // 持有的道具,包括两种令、战功和种子
// 奖励相关
receivedLv: number = 0; // 奖励领到几级
tasks: GVGTask[] = []; // 如果没有达成的任务就不放在这个数组里面
}
class LeagueResource {
food: number = 0; // 粮食
mineral: number = 0; // 矿物
wood: number = 0; // 木堆
}
class GVGTask {
id: number; // 任务id
count: number;
status: number; // 状态 0-未领取 1-已领取
}
export class GVGMainData {
configId: number = 0; // 赛期
period: number = 1; // 当前是什么期 1-组建期 2-备战期 3-激战期
countdownTime: number = 0; // 这个周期结束时间10位时间戳单位秒
type: number = 1; // 1-单服 2-跨服
hasLeague: boolean = false; // 是否拥有联军
// 左侧联军信息
leagueCode: string; // 联军唯一code
leader: LeagueLeaderInfo;
name: string; // 联军名
icon: number; // 图标
lv: number; // 联军等级
notice: string; // 公告
guildCnt: number; // 军团数量
memberCnt: number; // 玩家人数
teamCnt: number; // 里面的玩家的队伍数 TODO
leagueCe: number; // 联军内所有人总战力
// 个人信息
myInfo: LeaguePlayerData = new LeaguePlayerData();
// 激战期相关,城池背景
cities: number[] = []; // 占领的城池id
// 内政相关
resources: LeagueResource = new LeagueResource(); // 联盟的物资
activeTech: number[] = []; // 已激活了的科技树的id
sumTime: number = 0; // 今日贡献结算时间 10位时间戳
constructor(configId: number, period: number, countdownTime: number, type: number) {
this.configId = configId;
this.period = period;
this.countdownTime = countdownTime;
this.type = type;
}
setLeague(league: GVGLeagueType, serverNames: any) {
if(!league) return;
this.hasLeague = true;
let leader = <RoleType>league.leader;
this.leader = new LeagueLeaderInfo(leader, serverNames);
this.name = league.name;
this.icon = league.icon;
this.notice = league.notice;
this.guildCnt = league.guildCnt;
this.memberCnt = league.memberCnt;
this.leagueCe = league.leagueCe;
}
setLeagueParpare(leaguePrepare: GVGLeaguePrepareType) {
if(!leaguePrepare) return;
this.lv = leaguePrepare.lv;
this.resources = leaguePrepare.resources;
this.activeTech = leaguePrepare.tech.filter(cur => cur.status == 1).map(cur => cur.id);
}
setPlayerInfo(userData: GVGUserDataType, auth: number, canPrepare: boolean, canChooseJob: boolean, items: GVGItem[], tasks: GVGTask[]) {
this.myInfo.auth = auth;
this.myInfo.canPrepare = canPrepare;
this.myInfo.canChooseJob = canChooseJob;
this.myInfo.items = items;
if(userData) {
this.myInfo.job = userData?.job||0;
this.myInfo.receivedLv = userData?.receivedLv||0;
}
this.myInfo.tasks = tasks;
}
}
export class LeagueListInfo {
leagueCode: string; // 联军唯一id
name: string; // 联军名
icon: number; // icon
memberCnt: number; // 玩家人数
guildCnt: number; // 组成军团名
leaderName: string; // 大将军的姓名
leaderServerName: string; // 大将军所处小区名
leagueCe: number; // 联军战力
hasApply: boolean = false; // 是否申请过了
constructor(league: GVGLeagueType, serverNames: any) {
if(!league) return;
this.leagueCode = league.leagueCode;
this.name = league.name;
this.icon = league.icon;
this.memberCnt = league.memberCnt;
this.guildCnt = league.guildCnt;
this.leaderName = (<RoleType>league.leader).roleName;
this.leaderServerName = serverNames[(<RoleType>league.leader).serverId];
this.leagueCe = league.leagueCe;
}
setHasApply(hasApply: boolean) {
this.hasApply = hasApply;
}
}
export class LeagueSimpleInfo extends LeagueListInfo {
notice: string; // 公共
cities: number[] = []; // 占领的城池
constructor(league: GVGLeagueType, serverNames: any) {
super(league, serverNames);
if(!league) return;
this.notice = league.notice;
}
setCities(cities: number[]) {
this.cities = cities;
}
}
export class LeagueGuildInfo {
guildCode: string; // 军团唯一id
name: string; // 军团名
serverName: string; // 区服名
lv: number; // 军团等级
memberCnt: number; // 人数
leaderName: string; // 大将军的姓名
guildCe: number; // 军团战力
hasInvited: boolean; // 是否邀请过了
constructor(guild: GuildType, serverNames: any) {
if(!guild) return;
this.guildCode = guild.code;
this.name = guild.name;
this.serverName = serverNames[guild.serverId];
this.lv = guild.lv;
this.memberCnt = guild.memberCnt;
let leader = <RoleType>guild.leader;
this.leaderName = leader.roleName;
this.guildCe = guild.guildCe;
}
setHasInvited(hasInvited: boolean) {
this.hasInvited = hasInvited;
}
}
export class LeagueMemberListInfo {
roleId: string; // 玩家id
roleName: string; // 玩家名
lv: number; // 玩家等级
head: number; // 玩家头像
frame: number; // 玩家相框
guildName: string; // 所处军团名
serverName: string; // 所处小区名
job: number = 0; // 官职 1-贤臣 2-猛将
auth: number = 0; // 官职
active: number = 0; // 活跃
ce: number; // 玩家战力
isOnline: boolean; // 是否在线
quitTime: number; // 离线时间
constructor(role: RoleType, serverNames: any) {
if(!role) return;
this.roleId = role.roleId;
this.roleName = role.roleName;
this.lv = role.lv;
this.head = role.head;
this.frame = role.frame;
this.guildName = role.guildName;
this.serverName = serverNames[role.serverId];
this.ce = role.ce;
this.quitTime = role.quitTime;
this.isOnline = role.quitTime == role.loginTime;
}
setByUserData(data: GVGUserDataType) {
if(!data) return;
this.active = data.active;
this.job = data.job;
}
setAuth(auth: number) {
this.auth = auth;
}
}

View File

@@ -118,6 +118,7 @@ import { dicArtifactSeid, loadArtifactSeid } from "./dictionary/DicArtifactSeid"
import { DicArtifact } from "./dictionary/DicArtifact";
import { DicArtifactQuality } from "./dictionary/DicArtifactQuality";
import { dicGiftPackagePlan, loadGiftPackagePlan } from "./dictionary/DicGiftPackagePlan";
import { dicGVGPeriod, loadGVGPeriod } from './dictionary/DicGVGPeriod';
export const gameData = {
daily: dicDaily,
@@ -295,6 +296,7 @@ export const gameData = {
artifactQualityPlan: dicArtifactQualityPlan,
artifactSeid: dicArtifactSeid,
artifactByGroupAndQuality: dicArtifactsByGroup,
gvgPeriod: dicGVGPeriod,
};
// 在此提供一些原先在gamedata中提供的方法以便更方便获取gameData数据
@@ -1262,6 +1264,7 @@ function loadDatas() {
loadArtifactQuality();
loadArtifactQualityPlan();
loadArtifactSeid();
loadGVGPeriod();
}
// 重载dicParam

View File

@@ -0,0 +1,42 @@
// GVG周期表
import { FILENAME } from '../../consts'
import { parseNumberList, readFileAndParse } from '../util'
export interface DicGVGPeriod {
// 1-组建期 2-备战期 3-激战期
readonly periodType: number;
// 星期几 1-7
readonly day: number[];
// 星期几 1-7
readonly startDay: number;
// HH:mm, 组建期备战期填05:00。激战期填20:40
readonly startHour: number;
readonly startMinute: number;
readonly startSecond: number;
// HH:mm组建期填截止创建联军时间备战期填22:00激战期填21:40
readonly endHour: number;
readonly endMinute: number;
readonly endSecond: number;
}
export const dicGVGPeriod = new Map<number, DicGVGPeriod>();
export function loadGVGPeriod() {
dicGVGPeriod.clear();
let arr = readFileAndParse(FILENAME.DIC_GVG_PERIOD);
arr.forEach(o => {
o.day = parseNumberList(o.day);
o.startDay = o.day[0];
let startTime = o.startTime.split(':');
o.startHour = parseInt(startTime[0]);
o.startMinute = parseInt(startTime[1]);
o.startSecond = parseInt(startTime[2]);
let endTime = o.endTime.split(':');
o.endHour = parseInt(endTime[0]);
o.endMinute = parseInt(endTime[1]);
o.endSecond = parseInt(endTime[2]);
dicGVGPeriod.set(o.periodType, o);
});
arr = undefined;
}

View File

@@ -1,21 +1,22 @@
import { REFRESH_TIME, TIME_OUTPUT_TYPE, SHOP_REFRESH_TYPE } from '../consts';
import { isDebugTime } from './sdkUtil';
export const WEEK_TO_MS = 7 * 24 * 60 * 60 * 1000;
export const WEEK_TO_SECOND = 7 * 24 * 60 * 60;
export const DAY_TO_HOUR = 24;
export const DAY_TO_SECOND = 24 * 60 * 60;
export const DAY_TO_MS = 24 * 60 * 60 * 1000;
export const HOUR_TO_MINUTE = 60;
export const HOUR_TO_SECOND = 60 * 60;
export const HOUR_TO_MS = 60 * 60 * 1000;
export const MINUTE_TO_MS = 60 * 1000;
export const SECOND_TO_MS = 1000;
/**
* 时间
* @class
*/
class Time {
WEEK_TO_MS = 7 * 24 * 60 * 60 * 1000;
DAY_TO_HOUR = 24;
DAY_TO_SECOND = 24 * 60 * 60;
DAY_TO_MS = 24 * 60 * 60 * 1000;
HOUR_TO_MINUTE = 60;
HOUR_TO_SECOND = 60 * 60;
HOUR_TO_MS = 60 * 60 * 1000;
MINUTE_TO_MS = 60 * 1000;
SECOND_TO_MS = 1000;
now: Date; // 当前时间
time: Date; // 处理时间原料
outputType: number; // 输出格式
@@ -106,7 +107,7 @@ class Time {
if(time >= t) {
return t;
} else {
return new Date(t.getTime() - this.DAY_TO_MS);
return new Date(t.getTime() - DAY_TO_MS);
}
}
@@ -187,7 +188,7 @@ class Time {
let cur = this._getDayZeroPoint(curDate);
let pre = this._getDayZeroPoint(preDate);
return Math.floor((cur.getTime() - pre.getTime()) / this.DAY_TO_MS)
return Math.floor((cur.getTime() - pre.getTime()) / DAY_TO_MS)
}
/**
@@ -256,7 +257,7 @@ class Time {
if(this.time >= t) {
return this._returnResult(t);
} else {
return this._returnResult(t.getTime() - this.WEEK_TO_MS);
return this._returnResult(t.getTime() - WEEK_TO_MS);
}
}
@@ -287,10 +288,10 @@ class Time {
public getBeforeDayWithHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
let t = this._setHour(this.time.getTime(), hour, minute, seconds);
if(this.time >= t) {
let timestamp = t.getTime() - day * this.DAY_TO_MS;
let timestamp = t.getTime() - day * DAY_TO_MS;
return this._returnResult(timestamp);
} else {
let timestamp = t.getTime() - (day + 1) * this.DAY_TO_MS;
let timestamp = t.getTime() - (day + 1) * DAY_TO_MS;
return this._returnResult(timestamp);
}
}
@@ -306,10 +307,10 @@ class Time {
let t = this._setHour(this.time.getTime(), hour, minute, seconds, 0);
// console.log(t.getTime(), this.time.getTime());
if(this.time.getTime() > t.getTime()) {
let timestamp = t.getTime() + (day + 1) * this.DAY_TO_MS;
let timestamp = t.getTime() + (day + 1) * DAY_TO_MS;
return this._returnResult(timestamp);
} else {
let timestamp = t.getTime() + day * this.DAY_TO_MS;
let timestamp = t.getTime() + day * DAY_TO_MS;
return this._returnResult(timestamp);
}
}
@@ -323,7 +324,7 @@ class Time {
*/
public getBeforeDayAndSetHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
let t = this._setHour(this.time.getTime(), hour, minute, seconds);
let timestamp = t.getTime() - day * this.DAY_TO_MS;
let timestamp = t.getTime() - day * DAY_TO_MS;
return this._returnResult(timestamp);
}
@@ -336,7 +337,7 @@ class Time {
*/
public getAfterDayAndSetHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
let t = this._setHour(this.time.getTime(), hour, minute, seconds);
let timestamp = t.getTime() + day * this.DAY_TO_MS;
let timestamp = t.getTime() + day * DAY_TO_MS;
return this._returnResult(timestamp);
}
@@ -345,7 +346,7 @@ class Time {
* @param day 几天前
*/
public getBeforeDay(day: number) {
let timestamp = this.time.getTime() - day * this.DAY_TO_MS;
let timestamp = this.time.getTime() - day * DAY_TO_MS;
return this._returnResult(timestamp);
}
@@ -354,7 +355,7 @@ class Time {
* @param day 几天后
*/
public getAfterDay(day: number) {
let timestamp = this.time.getTime() + day * this.DAY_TO_MS;
let timestamp = this.time.getTime() + day * DAY_TO_MS;
return this._returnResult(timestamp);
}
@@ -363,7 +364,7 @@ class Time {
* @param hour 几小时前
*/
public getBeforeHour(hour: number) {
let timestamp = this.time.getTime() - hour * this.HOUR_TO_MS;
let timestamp = this.time.getTime() - hour * HOUR_TO_MS;
return this._returnResult(timestamp);
}
@@ -372,7 +373,7 @@ class Time {
* @param hour 几分钟前
*/
public getBeforeMinute(minute: number) {
let timestamp = this.time.getTime() - minute * this.MINUTE_TO_MS;
let timestamp = this.time.getTime() - minute * MINUTE_TO_MS;
return this._returnResult(timestamp);
}
@@ -393,7 +394,7 @@ class Time {
public getAfterDayByGap(preDate: Date, day: number) {
let gap = this._getDayGap(preDate, this.time);
let n = Math.floor(gap / day);
return this._returnResult(preDate.getTime() + n * day * this.DAY_TO_MS);
return this._returnResult(preDate.getTime() + n * day * DAY_TO_MS);
}
/**
@@ -401,7 +402,7 @@ class Time {
* @param day day天以内
*/
public checkDay(day: number = 1) {
if (this.time.getTime() - this.now.getTime() <= day * this.DAY_TO_MS) {
if (this.time.getTime() - this.now.getTime() <= day * DAY_TO_MS) {
return true;
}
return false;

View File

@@ -922,5 +922,19 @@
"name": "更新隐藏数据",
"module": "sys",
"type": "update"
},
{
"id": 133,
"api": "gm.gmHandler.updateGVGServerGroup",
"name": "更新GVG战区分配",
"module": "sys",
"type": "update"
},
{
"id": 134,
"api": "gm.gmHandler.updateGVGConfig",
"name": "更新GVG时间",
"module": "sys",
"type": "update"
}
]

View File

@@ -0,0 +1,86 @@
[
{
"id": 1,
"Type": 1,
"boxPoint": 100000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 2,
"Type": 1,
"boxPoint": 150000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 3,
"Type": 1,
"boxPoint": 200000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 4,
"Type": 1,
"boxPoint": 250000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 5,
"Type": 1,
"boxPoint": 300000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 6,
"Type": 1,
"boxPoint": 350000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 7,
"Type": 2,
"boxPoint": 50000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 8,
"Type": 2,
"boxPoint": 100000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 9,
"Type": 2,
"boxPoint": 150000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 10,
"Type": 2,
"boxPoint": 200000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 11,
"Type": 2,
"boxPoint": 250000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
},
{
"id": 12,
"Type": 2,
"boxPoint": 300000,
"boxReward": "31002&500",
"boxLeagueReward": "12&500"
}
]

View File

@@ -0,0 +1,197 @@
[
{
"id": 1,
"name": "小麦",
"type": 1,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "10&1",
"value": 100,
"reward": "31002&5000",
"leagueReward": "12&100"
},
{
"id": 2,
"name": "玉米",
"type": 1,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "31002&100",
"leagueConsume": "10&1",
"value": 150,
"reward": "31002&5001",
"leagueReward": "12&150"
},
{
"id": 3,
"name": "水稻",
"type": 1,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "31002&200",
"leagueConsume": "10&1",
"value": 200,
"reward": "31002&5002",
"leagueReward": "12&150"
},
{
"id": 4,
"name": "普通铲子",
"type": 2,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "10&2",
"value": 15,
"reward": "31002&5003",
"leagueReward": "12&200"
},
{
"id": 5,
"name": "中级铲子",
"type": 2,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "31002&100",
"leagueConsume": "10&2",
"value": 20,
"reward": "31002&5004",
"leagueReward": "12&300"
},
{
"id": 6,
"name": "高级铲子",
"type": 2,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "31002&200",
"leagueConsume": "10&2",
"value": 30,
"reward": "31002&5005",
"leagueReward": "12&300"
},
{
"id": 7,
"name": "石斧",
"type": 3,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "10&2",
"value": 25,
"reward": "31002&5006",
"leagueReward": "12&200"
},
{
"id": 8,
"name": "铜斧",
"type": 3,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "31002&100",
"leagueConsume": "10&2",
"value": 30,
"reward": "31002&5007",
"leagueReward": "12&300"
},
{
"id": 9,
"name": "铁斧",
"type": 3,
"refreshType": 1,
"image_id": "&",
"info": "&",
"consume": "31002&200",
"leagueConsume": "10&2",
"value": 40,
"reward": "31002&5008",
"leagueReward": "12&300"
},
{
"id": 10,
"name": "内政令",
"type": 4,
"refreshType": 2,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "&",
"value": 0,
"reward": "&",
"leagueReward": "&"
},
{
"id": 11,
"name": "征战令",
"type": 4,
"refreshType": 2,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "&",
"value": 0,
"reward": "&",
"leagueReward": "&"
},
{
"id": 12,
"name": "战功",
"type": 5,
"refreshType": 2,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "&",
"value": 0,
"reward": "&",
"leagueReward": "&"
},
{
"id": 13,
"name": "复活令",
"type": 6,
"refreshType": 2,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "&",
"value": 0,
"reward": "&",
"leagueReward": "&"
},
{
"id": 14,
"name": "匕首",
"type": 6,
"refreshType": 2,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "&",
"value": 0,
"reward": "&",
"leagueReward": "&"
},
{
"id": 15,
"name": "箭塔",
"type": 6,
"refreshType": 2,
"image_id": "&",
"info": "&",
"consume": "&",
"leagueConsume": "&",
"value": 0,
"reward": "&",
"leagueReward": "&"
}
]

View File

@@ -0,0 +1,82 @@
[
{
"id": 1,
"lv": 1,
"food": 2000,
"mineral": 1000,
"wood": 1000,
"reward": "31002&500|31001&10000"
},
{
"id": 2,
"lv": 2,
"food": 2200,
"mineral": 1100,
"wood": 1100,
"reward": "31002&500|31001&10000"
},
{
"id": 3,
"lv": 3,
"food": 2400,
"mineral": 1200,
"wood": 1200,
"reward": "31002&500|31001&10000"
},
{
"id": 4,
"lv": 4,
"food": 2600,
"mineral": 1300,
"wood": 1300,
"reward": "31002&500|31001&10000"
},
{
"id": 5,
"lv": 5,
"food": 2800,
"mineral": 1400,
"wood": 1400,
"reward": "31002&500|31001&10000"
},
{
"id": 6,
"lv": 6,
"food": 3000,
"mineral": 1500,
"wood": 1500,
"reward": "31002&500|31001&10000"
},
{
"id": 7,
"lv": 7,
"food": 3200,
"mineral": 1600,
"wood": 1600,
"reward": "31002&500|31001&10000"
},
{
"id": 8,
"lv": 8,
"food": 3400,
"mineral": 1700,
"wood": 1700,
"reward": "31002&500|31001&10000"
},
{
"id": 9,
"lv": 9,
"food": 3600,
"mineral": 1800,
"wood": 1800,
"reward": "31002&500|31001&10000"
},
{
"id": 10,
"lv": 10,
"food": 3800,
"mineral": 1900,
"wood": 1900,
"reward": "31002&500|31001&10000"
}
]

View File

@@ -0,0 +1,20 @@
[
{
"periodType": 1,
"day": "7&",
"startTime": "05:00:00",
"endTime": "05:00:00"
},
{
"periodType": 2,
"day": "1&2&3&4&5",
"startTime": "05:00:00",
"endTime": "22:00:00"
},
{
"periodType": 3,
"day": "6&",
"startTime": "20:40:00",
"endTime": "21:40:00"
}
]

View File

@@ -0,0 +1,332 @@
[
{
"id": 1,
"name": "1级农庄",
"lv": 1,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "1&3",
"value": "10",
"sum": 100
},
{
"id": 2,
"name": "2级农庄",
"lv": 2,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "1&5",
"value": "120",
"sum": 100
},
{
"id": 3,
"name": "3级农庄",
"lv": 3,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "1&6",
"value": "130",
"sum": 100
},
{
"id": 4,
"name": "4级农庄",
"lv": 4,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "2&6",
"value": "140",
"sum": 100
},
{
"id": 5,
"name": "5级农庄",
"lv": 5,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "2&10",
"value": "150",
"sum": 100
},
{
"id": 6,
"name": "6级农庄",
"lv": 6,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "2&12",
"value": "160",
"sum": 100
},
{
"id": 7,
"name": "7级农庄",
"lv": 7,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "3&6",
"value": "170",
"sum": 100
},
{
"id": 8,
"name": "8级农庄",
"lv": 8,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "3&10",
"value": "180",
"sum": 100
},
{
"id": 9,
"name": "9级农庄",
"lv": 9,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "3&12",
"value": "190",
"sum": 100
},
{
"id": 10,
"name": "10级农庄",
"lv": 10,
"type": 1,
"limit": "X名武将X星",
"limitType": 1,
"limitParams": "5&12",
"value": "1100",
"sum": 100
},
{
"id": 11,
"name": "1级矿山",
"lv": 1,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "1&1",
"value": "11001021505315010",
"sum": 200
},
{
"id": 12,
"name": "2级矿山",
"lv": 2,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "1&2",
"value": "11001021505315010",
"sum": 200
},
{
"id": 13,
"name": "3级矿山",
"lv": 3,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "1&3",
"value": "11001021505315010",
"sum": 200
},
{
"id": 14,
"name": "4级矿山",
"lv": 4,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "1&4",
"value": "11001021505315010",
"sum": 200
},
{
"id": 15,
"name": "5级矿山",
"lv": 5,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "1&5",
"value": "11001021505315010",
"sum": 200
},
{
"id": 16,
"name": "6级矿山",
"lv": 6,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "1&6",
"value": "11001021505315010",
"sum": 200
},
{
"id": 17,
"name": "7级矿山",
"lv": 7,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "4&3",
"value": "11001021505315010",
"sum": 200
},
{
"id": 18,
"name": "8级矿山",
"lv": 8,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "4&4",
"value": "11001021505315010",
"sum": 200
},
{
"id": 19,
"name": "9级矿山",
"lv": 9,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "4&5",
"value": "11001021505315010",
"sum": 200
},
{
"id": 20,
"name": "10级矿山",
"lv": 10,
"type": 2,
"limit": "X件装备X星",
"limitType": 2,
"limitParams": "4&6",
"value": "215010320010415010",
"sum": 200
},
{
"id": 21,
"name": "1级木堆",
"lv": 1,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 100000,
"value": "3100",
"sum": 100
},
{
"id": 22,
"name": "2级木堆",
"lv": 2,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 200000,
"value": "3150",
"sum": 100
},
{
"id": 23,
"name": "3级木堆",
"lv": 3,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 300000,
"value": "3200",
"sum": 100
},
{
"id": 24,
"name": "4级木堆",
"lv": 4,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 400000,
"value": "3250",
"sum": 100
},
{
"id": 25,
"name": "5级木堆",
"lv": 5,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 500000,
"value": "3300",
"sum": 100
},
{
"id": 26,
"name": "6级木堆",
"lv": 6,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 600000,
"value": "3350",
"sum": 100
},
{
"id": 27,
"name": "7级木堆",
"lv": 7,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 700000,
"value": "3400",
"sum": 100
},
{
"id": 28,
"name": "8级木堆",
"lv": 8,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 800000,
"value": "3450",
"sum": 100
},
{
"id": 29,
"name": "9级木堆",
"lv": 9,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 900000,
"value": "3500",
"sum": 100
},
{
"id": 30,
"name": "10级木堆",
"lv": 10,
"type": 3,
"limit": "最强6人战力达XXXX",
"limitType": 3,
"limitParams": 1000000,
"value": "3600",
"sum": 100
}
]

View File

@@ -0,0 +1,110 @@
[
{
"id": 1,
"name": "贤臣1",
"content": "资源产量提升5%",
"type": 1,
"param": "5&",
"nodeSort": 1,
"levelSeid": 0,
"levelLimit": 1,
"prepositionId": "&",
"consume": "12&5000"
},
{
"id": 2,
"name": "猛将1",
"content": "征战中原联军成员攻击提升5%",
"type": 2,
"param": "&",
"nodeSort": 1,
"levelSeid": "1001&",
"levelLimit": 1,
"prepositionId": "&",
"consume": "12&5000"
},
{
"id": 3,
"name": "贤臣2",
"content": "资源产量提升10%",
"type": 1,
"param": "10&",
"nodeSort": 2,
"levelSeid": 0,
"levelLimit": 2,
"prepositionId": "1&",
"consume": "12&5000"
},
{
"id": 4,
"name": "猛将2",
"content": "征战中原联军成员攻击提升10%",
"type": 2,
"param": "&",
"nodeSort": 2,
"levelSeid": "1001&",
"levelLimit": 2,
"prepositionId": "2&",
"consume": "12&5000"
},
{
"id": 5,
"name": "激战1",
"content": "激战期时联军成员攻击提升2%",
"type": 3,
"param": "&",
"nodeSort": 3,
"levelSeid": "1001&",
"levelLimit": 2,
"prepositionId": "3&|4&",
"consume": "12&5000"
},
{
"id": 6,
"name": "激战2",
"content": "激战期时联军成员攻击提升5%",
"type": 3,
"param": "&",
"nodeSort": 4,
"levelSeid": "1001&",
"levelLimit": 4,
"prepositionId": "5&",
"consume": "12&5000"
},
{
"id": 7,
"name": "复活1",
"content": "激战期时联军成员复活cd减少30s",
"type": 4,
"param": "30&",
"nodeSort": 5,
"levelSeid": 0,
"levelLimit": 4,
"prepositionId": "6&",
"consume": "12&5000"
},
{
"id": 8,
"name": "箭塔1",
"content": "联军中随机20名成员获得箭塔箭塔每10s给该位置所有敌军减5点耐久箭头耐久为50点",
"type": 5,
"param": "10&5&50",
"nodeSort": 6,
"levelSeid": 0,
"levelLimit": 6,
"prepositionId": "7&",
"consume": "12&5000"
},
{
"id": 9,
"name": "攻城车1",
"content": "联军中随机20名成员获得攻城车使用攻城车道具可击杀1名敌军",
"type": 6,
"param": "20&",
"nodeSort": 6,
"levelSeid": 0,
"levelLimit": 6,
"prepositionId": "7&",
"consume": "12&5000"
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
[
{
"id": 1,
"rankMin": 1,
"rankMax": 2,
"rankReward": "31002&800",
"rankLeagueReward": "12&800"
},
{
"id": 2,
"rankMin": 2,
"rankMax": 3,
"rankReward": "31002&700",
"rankLeagueReward": "12&700"
},
{
"id": 3,
"rankMin": 3,
"rankMax": 5,
"rankReward": "31002&600",
"rankLeagueReward": "12&600"
},
{
"id": 4,
"rankMin": 5,
"rankMax": 10,
"rankReward": "31002&500",
"rankLeagueReward": "12&500"
},
{
"id": 5,
"rankMin": 10,
"rankMax": 50,
"rankReward": "31002&400",
"rankLeagueReward": "12&400"
},
{
"id": 6,
"rankMin": 50,
"rankMax": 60,
"rankReward": "31002&300",
"rankLeagueReward": "12&300"
},
{
"id": 7,
"rankMin": 60,
"rankMax": 70,
"rankReward": "31002&200",
"rankLeagueReward": "12&200"
},
{
"id": 8,
"rankMin": 70,
"rankMax": 80,
"rankReward": "31002&150",
"rankLeagueReward": "12&150"
},
{
"id": 9,
"rankMin": 80,
"rankMax": 100,
"rankReward": "31002&100",
"rankLeagueReward": "12&100"
},
{
"id": 10,
"rankMin": 100,
"rankMax": 0,
"rankReward": "31002&50",
"rankLeagueReward": "12&50"
}
]

View File

@@ -0,0 +1,67 @@
[
{
"id": 1,
"rankMin": 0,
"rankMax": 10,
"rangeBeforeFrom": 0,
"rangeBeforeTo": 0,
"rangeBeforeNum": 0,
"rangeAfterFrom": 0,
"rangeAfterTo": 0,
"rangeAfterNum": 0,
"topChallengeFrom": 1,
"topChallengeTo": 10
},
{
"id": 2,
"rankMin": 10,
"rankMax": 50,
"rangeBeforeFrom": 10,
"rangeBeforeTo": -1,
"rangeBeforeNum": 20,
"rangeAfterFrom": 0,
"rangeAfterTo": 0,
"rangeAfterNum": 0,
"topChallengeFrom": 1,
"topChallengeTo": 10
},
{
"id": 3,
"rankMin": 50,
"rankMax": 150,
"rangeBeforeFrom": 5,
"rangeBeforeTo": 50,
"rangeBeforeNum": 20,
"rangeAfterFrom": 50,
"rangeAfterTo": -1,
"rangeAfterNum": 5,
"topChallengeFrom": 1,
"topChallengeTo": 5
},
{
"id": 4,
"rankMin": 150,
"rankMax": 250,
"rangeBeforeFrom": 50,
"rangeBeforeTo": 150,
"rangeBeforeNum": 25,
"rangeAfterFrom": 150,
"rangeAfterTo": -1,
"rangeAfterNum": 5,
"topChallengeFrom": 0,
"topChallengeTo": 0
},
{
"id": 5,
"rankMin": 250,
"rankMax": -1,
"rangeBeforeFrom": 150,
"rangeBeforeTo": 250,
"rangeBeforeNum": 30,
"rangeAfterFrom": 0,
"rangeAfterTo": 0,
"rangeAfterNum": 0,
"topChallengeFrom": 0,
"topChallengeTo": 0
}
]

View File

@@ -0,0 +1,123 @@
[
{
"id": 1,
"vestigeId": 1,
"name": "齐都遗址",
"mapType": "1&2",
"imageName": "&",
"additionType": 1,
"additionValue": "2&1000",
"content": "枪兵",
"position": "&"
},
{
"id": 2,
"vestigeId": 2,
"name": "楚都遗址",
"mapType": "1&2",
"imageName": "&",
"additionType": 1,
"additionValue": "6&1000",
"content": "策士",
"position": "&"
},
{
"id": 3,
"vestigeId": 3,
"name": "燕都遗址",
"mapType": "1&2",
"imageName": "&",
"additionType": 1,
"additionValue": "5&1000",
"content": "游侠",
"position": "&"
},
{
"id": 4,
"vestigeId": 4,
"name": "韩都遗址",
"mapType": "1&2",
"imageName": "&",
"additionType": 1,
"additionValue": "4&1000",
"content": "弓兵",
"position": "&"
},
{
"id": 5,
"vestigeId": 5,
"name": "赵都遗址",
"mapType": "1&2",
"imageName": "&",
"additionType": 1,
"additionValue": "3&1000",
"content": "骑兵",
"position": "&"
},
{
"id": 6,
"vestigeId": 6,
"name": "魏都遗址",
"mapType": "1&2",
"imageName": "&",
"additionType": 1,
"additionValue": "1&1000",
"content": "步兵",
"position": "&"
},
{
"id": 7,
"vestigeId": 7,
"name": "山巅帝陵",
"mapType": "1&2",
"imageName": "&",
"additionType": 2,
"additionValue": "1&1000",
"content": "魏国",
"position": "&"
},
{
"id": 8,
"vestigeId": 8,
"name": "崖底河泽",
"mapType": "1&2",
"imageName": "&",
"additionType": 2,
"additionValue": "2&1000",
"content": "吴国",
"position": "&"
},
{
"id": 9,
"vestigeId": 9,
"name": "深山迷林",
"mapType": "1&2",
"imageName": "&",
"additionType": 2,
"additionValue": "3&1000",
"content": "蜀国",
"position": "&"
},
{
"id": 10,
"vestigeId": 10,
"name": "桃源古村",
"mapType": "1&2",
"imageName": "&",
"additionType": 2,
"additionValue": "4&1000",
"content": "群雄",
"position": "&"
},
{
"id": 11,
"vestigeId": 11,
"name": "鹿鸣幽谷",
"mapType": "1&2",
"imageName": "&",
"additionType": 3,
"additionValue": "2&1000",
"content": "女性",
"position": "&"
}
]

View File

@@ -33,6 +33,6 @@
"DEBUG_TIME": 1,
"CHECK_WORD": 1,
"CAN_PAY": 1,
"SKIP_ENCODE": 0,
"SKIP_ENCODE": 1,
"NEED_REBATE": 0
}