Files
ZYZ/game-server/app/services/guildActivity/guildActivityService.ts
2022-06-01 20:51:31 +08:00

809 lines
32 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ServerlistModel, ServerlistType } from "../../db/Serverlist";
import { RoleModel } from "../../db/Role";
import { GUILDACTIVITY } from "../../pubUtils/dicParam";
import { gameData, getGuildAuctionRewards, getCityActivityRewards } from "../../pubUtils/data";
import { getCurDay, nowSeconds, getTimeFun } from "../../pubUtils/timeUtil";
import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, AUCTION_SOURCE, MAIL_TYPE, CITY_STATUS, DEBUG_MAGIC_WORD, GUILD_POINT_WAYS, TASK_TYPE, AUCTION_TIME, CITY_ACTIVITY_DOOR, ABI_TYPE, PUSH_ROUTE, RACE_ACTIVITY_STATUS } from "../../consts";
import { Record, UserGuildActivityRecModel } from "../../db/UserGuildActivityRec";
import { GateMembersRec, CityParam, Member, WoodenHorse } from "../../domain/battleField/guildActivity";
import { DicGuildActivity } from "../../pubUtils/dictionary/DicGuildActivity";
import { getAllServers, getRoleOnlineInfo } from "../redisService";
import { SimpleGuildRankParam, SimpleRoleRankParam, GuildRankInfo, RoleRankInfo } from "../../domain/rank";
import { pinus } from "pinus";
import { GuildActivityRecordModel } from "../../db/GuildActivityRec";
import { genAuction } from "../auctionService";
import { sendMailByContent } from "../mailService";
import { GuildActivityCityType, GuildActivityCityModel } from "../../db/GuildActivityCity";
import { DicCityActivity } from "../../pubUtils/dictionary/DicCityActivity";
import { CityActivityObject } from "./cityActivityObj";
import { GateActivityObject } from "./gateActivityObj";
import { RaceActivityObject } from "./raceActivityObj";
import { Rank } from "../rankService";
import { BossInstanceModel } from "../../db/BossInstance";
import { UserGuildModel } from "../../db/UserGuild";
import { addActive } from "../guildService";
import { ActivePlayer, GuildRecord, ServerRecordModel } from "../../db/ServerRecords";
import { Attack } from "../../domain/battleField/pvp";
import { getHonourObject } from "../role/rewardService";
import { sendMessageToCityWithSuc, sendMessageToGuildWithSuc, sendMessageToServerWithSuc } from "../pushService";
let gateActivityObj: GateActivityObject;
let cityActivityObj: CityActivityObject;
let raceActivityObj: RaceActivityObject;
export function getGateActivityObj() {
if (!gateActivityObj) {
gateActivityObj = new GateActivityObject();
}
return gateActivityObj;
}
export function getCityActivityObj() {
if (!cityActivityObj) {
cityActivityObj = new CityActivityObject();
}
return cityActivityObj;
}
export function getRaceActivityObj() {
if (!raceActivityObj) {
raceActivityObj = new RaceActivityObject();
}
return raceActivityObj;
}
export function clearActivityObj() {
gateActivityObj = undefined;
cityActivityObj = undefined;
raceActivityObj = undefined;
}
/**
* 定时任务,获得前一天的活跃玩家中位数武将战力
*/
export async function setPreDayActiveData(servers: ServerlistType[]) {
for (let server of servers) {
let roles = await RoleModel.getActivePlayers(server.id);
let activePlayerCnt = roles.length;
let activePlayerCe = 0, activePlayers: ActivePlayer[] = [];
let activeGuilds: GuildRecord[] = [];
for(let i = 0; i < roles.length; i++) {
let role = roles[i];
let activePlayer = new ActivePlayer(role);
if(i < 10) {
activePlayerCe += role.topLineupCe;
activePlayers.push(activePlayer);
}
if(role.hasGuild) {
let guildRecord = activeGuilds.find(cur => cur.guildCode == role.guildCode);
if(!guildRecord) {
activeGuilds.push({ guildCode: role.guildCode, players: [activePlayer] });
} else {
guildRecord.players.push(activePlayer);
}
}
}
await ServerRecordModel.updateData(server.id, { activePlayerCnt, activePlayerCe, activePlayers, activeGuilds });
}
return servers;
}
/**
* 获得本服前一天活跃玩家中位数玩家的最强武将战力
* @param serverId
*/
export async function getPreDayActiveData(serverId: number) {
let record = await ServerRecordModel.findTodayData(serverId);
return record;
}
/**
* 根据当前时间判断军团活动倒计时
* @param id 军团活动id
*/
export function getGuildActivityStatus(id: number) {
let dicGuildActivity = gameData.guildActivity.get(id);
if (!dicGuildActivity) return false;
return getGuildActivityByDic(dicGuildActivity);
}
export async function getAllGuildActivityStatus(guildCode: string, serverId: number) {
let guildActivities: { aid: number, status: number, time: number, isOpen: boolean, isCompleted?: boolean }[] = [];
for(let [ aid, dicGuildActivity ] of gameData.guildActivity) {
let res = getGuildActivityByDic(dicGuildActivity);
let isCompleted = res.isOpen;
if(res.status == GUILD_ACTIVITY_STATUS.START && guildCode) {
let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, aid);
if(guildActivityRec) isCompleted = guildActivityRec.isCompleted;
}
guildActivities.push({aid, ...res, isCompleted});
}
return guildActivities;
}
export function getGuildActivityByDic(dicGuildActivity: DicGuildActivity) {
let t = getTimeFun();
// console.log('*********', dicGuildActivity.startTime, dicGuildActivity.startMinute, dicGuildActivity.startSeconds)
let startTime = <number>t.getTimeWithHour(dicGuildActivity.startTime, dicGuildActivity.startMinute, dicGuildActivity.startSeconds);
let countdownTime = <number>t.getTimeWithHour(dicGuildActivity.countDown);
let { duringTime, openDay } = dicGuildActivity;
let endTime = startTime + duringTime;
let status = 0, time = 0;
let now = nowSeconds();
if (now >= countdownTime && now < startTime) {
status = GUILD_ACTIVITY_STATUS.WAITING;
time = startTime - now;
} else if (now >= startTime && now < endTime) {
status = GUILD_ACTIVITY_STATUS.START;
time = endTime - now;
} else {
status = GUILD_ACTIVITY_STATUS.END;
}
let day = getCurDay();
let isOpen = openDay.includes(day);
return {
status, time, isOpen
}
}
/**
* 根据每回合上报数据判断军功
* @param aid
* @param record
* @param memberRecord
*/
export function getRecordScore(aid: number, round: number, record: { round: number, dataId: number }[], memberRecord: GateMembersRec) {
let dicGuildActivity = gameData.guildActivity.get(aid);
if (!dicGuildActivity) return false;
let dicWarJson = gameData.warJson.get(dicGuildActivity.warid);
if (!dicWarJson) return false;
let { round: curRound, enemies: historyEnemies } = memberRecord;
let sum = 0, newRecords = new Array<Record>();
for (let { round, dataId } of record) {
if (!historyEnemies.includes(dataId)) {
let enemy = dicWarJson.find(cur => cur.dataId == dataId);
let enemyType = enemy.enemyType;
let score = gameData.gateActivityPoint.get(enemyType);
newRecords.push({ round, dataId, score, enemyType });
sum += score;
historyEnemies.push(dataId);
}
}
for (let i = curRound + 1; i <= round; i++) {
sum += gameData.gateActivityPoint.get(GET_POINT_WAYS.ROUND_START);
memberRecord.round = i;
}
return { score: sum, newRecords, memberRecord }
}
export async function getGateActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) {
let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true);
r.setGenerFieldsFun(generGuildActivityRankField);
let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode });
if (!myGuildRank) {
myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0);
}
let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }, true);
myR.setGenerFieldsFun(generGuildActivityMemberRankField);
let { ranks: memberRank, myRank: myMemberRank } = await myR.getRankListWithMyRank({ roleId });
if (roleName && !myMemberRank) {
myMemberRank = await myR.generMyRankWithRole(roleId, 0, 0);
}
return { guildRank, myGuildRank, memberRank, myMemberRank }
}
export async function getCityActivityRank(guildCode: string, serverId: number, cityId: number, roleId?: string, roleName?: string) {
let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true);
r.setGenerFieldsFun(generGuildActivityRankField);
let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode });
if (!myGuildRank) {
myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0);
}
let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }, true);
myR.setGenerFieldsFun(generGuildActivityMemberRankField);
let { ranks: memberRank, myRank: myMemberRank } = await myR.getRankListWithMyRank({ roleId });
if (roleName && !myMemberRank) {
myMemberRank = await myR.generMyRankWithRole(roleId, 0, 0);
}
return { guildRank, myGuildRank, memberRank, myMemberRank }
}
/**
* 获取和自己同屏的5个木牛流马
* @param guildCode
* @param serverId
*/
export async function getWoodenHorseList(guildCode: string, serverId: number) {
let obj = getRaceActivityObj();
let { myGuildRank, guildRank } = await obj.getRanks(serverId, guildCode);
let myRank = myGuildRank?.rank||0;
let startRank = myRank - 2 > 0 ? myRank - 2 : 1;
let endRank = startRank + 4;
let woodenHorseList = new Array<WoodenHorse>();
for (let { rank, code } of guildRank) {
if(rank >= startRank && rank <= endRank) {
let woodenHorse = await obj.getWoodenHorse(code, serverId);
if (woodenHorse) {
woodenHorseList.push(woodenHorse);
}
}
}
return woodenHorseList;
}
function generGuildActivityRankField(param: GuildRankInfo) {
let { rank, code, name, num } = param;
return new SimpleGuildRankParam(rank, code, name, num);
}
function generGuildActivityMemberRankField(param: RoleRankInfo) {
let { rank, roleId, roleName, num } = param;
return new SimpleRoleRankParam(rank, roleId, roleName, num);
}
/**
* 对这个guild服内所有军团发排行榜信息
* @param aid 活动类型
*/
export async function sendAllGuildRanks(aid: number) {
if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) {
let obj = getGateActivityObj();
let guilds = obj.getGuilds();
for (let [serverId, guildCodes] of guilds) {
for (let guildCode of guildCodes) {
let ranks = await getGateActivityRank(guildCode, serverId);
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GATE_ACT_RANK, ranks);
}
}
} else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) {
let obj = getCityActivityObj();
let { cities } = obj.getAllCities();
// console.log(JSON.stringify(cities));
for (let { serverId, cityId, guildCodes } of cities) {
for (let guildCode of guildCodes) {
let ranks = await getCityActivityRank(guildCode, serverId, cityId);
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.CITY_ACT_RANK, ranks);
}
}
}
}
/**
* 活动结算奖励
* @param aid 活动类型
*/
export async function settleGuildActivityReward(aid: number) {
if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) {
let obj = getGateActivityObj();
let guilds = obj.getGuilds();
for (let [serverId, guildCodes] of guilds) {
// console.log('***** serverId', serverId, 'guildCodes', guildCodes);
for (let guildCode of guildCodes) {
await gateActivitySettleReward(guildCode, serverId);
}
}
} else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) {
let obj = getCityActivityObj();
let { cities } = obj.getAllCities();
for (let { serverId, cityId } of cities) {
await cityActivitySettleReward(cityId, serverId);
}
} else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) {
let obj = getRaceActivityObj();
for (let { guildCode, serverId } of obj.guildList) {
let woodenHorse = await obj.getWoodenHorse(guildCode, serverId);
if (woodenHorse && woodenHorse.status != 0 && !obj.hasSend(guildCode)) {
await raceActivitySettleReward(guildCode, woodenHorse);
}
}
}
}
// 全服发送结束新号
export async function sendEndMsgToAllServer() {
let serverlist = await getAllServers();
for (let serverId of serverlist) {
await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GUILD_ACTIVITY_END, {});
await sendGuildActivityStatus(serverId);
}
}
export async function sendGuildActivityStatus(serverId: number) {
let guildActivities: { aid: number, status: number, time: number, isOpen: boolean }[] = [];
gameData.guildActivity.forEach((dicGuildActivity, aid) => {
let res = getGuildActivityByDic(dicGuildActivity);
guildActivities.push({aid ,...res});
});
await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GUILD_ACTIVITY_STATUS, { guildActivities });
}
/**
* 单个城池城门血条破了之后给他发奖励
* @param guildCode 军团code
*/
export async function sendSingleCityActEndMsg(cityId: number, serverId: number) {
let obj = getCityActivityObj();
let guildCodes = obj.getGuildsInCity(serverId, cityId);
for (let guildCode of guildCodes) {
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_ACTIVITY_END, {});
}
await cityActivitySettleReward(cityId, serverId);
}
/**
* 单个军团抵达赛道之后给他发奖励
* @param guildCode 军团code
*/
export async function sendSingleRaceActEndMsg(guildCode: string, woodenHorse: WoodenHorse) {
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_ACTIVITY_END, {});
await raceActivitySettleReward(guildCode, woodenHorse);
}
/**
* 结算蛮夷入侵奖励
* @param guildCode 军团code
* @param serverId 服务器id
*/
export async function gateActivitySettleReward(guildCode: string, serverId: number) {
console.log('gateActivitySettleReward', guildCode, serverId);
let obj = getGateActivityObj();
let { members } = obj.getObj(guildCode, serverId);
// console.log('***** gateHp', gateHp, 'members', members);
let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true);
let rank = await r.getMyRank({ guildCode });
let guildScore = await r.getMyScore({ guildCode });
// console.log('****** ranks', rank, 'guildScore', guildScore);
let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank);
// console.log('***** rewards', JSON.stringify(rewards));
let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, {
isSuccess: true,
isCompleted: true,
rank, score: guildScore,
members, memberCnt: members.length,
auctionType: AUCTION_SOURCE.GATE,
rewards: rewards.map(cur => cur.goods)
});
// 结算功勋等奖励
let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY);
let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }, true);
let hasSentMember: string[] = [];
let ranks = <RoleRankInfo[]>await myR.getRankByRange();
for (let { rank, roleId, num: myScore } of ranks) {
if(hasSentMember.indexOf(roleId) == -1) {
let honour = dic.honour + myScore * GUILDACTIVITY.GATEACTIVITY_HONOUR_RATIO;
await updateUserRecAndSendHonour(honour, myScore, rank, roleId);
hasSentMember.push(roleId);
}
}
for (let { roleId } of members) {
// 只参加了,没有分数的人
if(hasSentMember.indexOf(roleId) == -1) {
await updateUserRecAndSendHonour(dic.honour, 0, 0, roleId);
hasSentMember.push(roleId);
}
// 发放活跃
await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值
}
// 加入拍卖行
await genAuction(guildCode, AUCTION_SOURCE.GATE, rec.code, serverId, rewards);
// obj.delGuildRecord(guildCode, serverId);
}
async function updateUserRecAndSendHonour(honour: number, myScore: number, rank: number, roleId: string) {
let honourObj = getHonourObject(Math.floor(honour));
await sendMailByContent(MAIL_TYPE.GUILD_ACTIVITY_REWARD, roleId, { goods: [honourObj] })
await UserGuildActivityRecModel.updateInfoByRoleId(roleId, { score: myScore, rank });
}
/**
* 结算诸侯入侵奖励
* @param cityId 城镇id
* @param serverId 服务器id
*/
export async function cityActivitySettleReward(cityId: number, serverId: number) {
let obj = getCityActivityObj();
if(obj.hasSent(serverId, cityId)) return;
let dicCity = gameData.cityActivity.get(cityId);
if (!dicCity) return;
let {gateHp} = await obj.getGateHpAndInc(serverId, cityId);
let isSuccess = gateHp <= 0; // 血条未击破则没有占领军团
let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true);
let ranks = <GuildRankInfo[]>await r.getRankByRange();
for (let { rank: guildRank, code: guildCode, name, num } of ranks) {
if (guildRank == 1) {
if (isSuccess) {
console.log(dicCity)
await GuildActivityCityModel.guard(serverId, cityId, dicCity?.nextCity, guildCode, name); // 占领
} else {
await GuildActivityCityModel.guard(serverId, cityId, 0, "", ""); // 无人能占领
}
}
let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, guildRank, cityId);
let members = obj.getMembersOfGuild(guildCode);
let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, {
memberCnt: members.length, members,
isSuccess, isCompleted: true,
rank: guildRank, damage: num, remainGateHp: gateHp,
rewards: rewards.map(cur => cur.goods),
auctionType: AUCTION_SOURCE.CITY,
});
// 奖励加入拍卖行
await genAuction(guildCode, AUCTION_SOURCE.CITY, rec.code, serverId, rewards);
let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);
let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }, true);
let ranks = <RoleRankInfo[]>await myR.getRankByRange();
let userRank = 0;
let hasSentMember: string[] = [];
for (let { rank, roleId, num: myScore } of ranks) {
if(hasSentMember.indexOf(roleId) == -1) {
let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, rank);
await updateUserRecAndSendHonour(honour, myScore, rank, roleId);
hasSentMember.push(roleId);
}
userRank = rank;
}
for (let { roleId } of members) { // 只参加了,没有分数的人
if(hasSentMember.indexOf(roleId) == -1) {
let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, userRank);
await updateUserRecAndSendHonour(honour, 0, 0, roleId);
hasSentMember.push(roleId);
}
// 发放活跃
await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值
}
}
obj.delCityRecord(cityId, serverId);
}
/**
* 清空完declareGuilds之后做下一次活动的自动宣战
*/
export async function autoDeclare(serverId: number) {
await GuildActivityCityModel.clearGuardAndStartNext(serverId);
for(let [ cityId ] of gameData.cityActivity) {
let msg = { cityId, declareGuildCode: "", declareCount: 0 };
await sendMessageToCityWithSuc(cityId, PUSH_ROUTE.GUILD_CITY_DECLARE, msg);
}
}
/**
* 获取活动参加者
* @param guildCode 军团code
* @param sourceType 拍卖类型 AUCTION_SOURCE
* @param sourceCode 活动唯一code
*/
export async function participants(guildCode: string, sourceType: number, sourceCode: string) {
if(sourceCode == DEBUG_MAGIC_WORD) {
let userGuilds = await UserGuildModel.getListByGuild(guildCode);
return userGuilds.map(cur => {
return { roleId: cur.roleId, job: cur.job }
})
}
if (sourceType == AUCTION_SOURCE.BOSS) {
let rec = await BossInstanceModel.findBySourceCode(guildCode, sourceCode);
if (!rec) return [];
return rec.ranks.map(cur => {
return { roleId: cur.roleId, job: cur.job }
});
} else {
let rec = await GuildActivityRecordModel.findBySourceCode(guildCode, sourceType, sourceCode);
if (!rec) return [];
return rec.members || [];
}
}
/**
* 获取诸侯入侵各个城池状态
* @param guildCode 我方军团
* @param dbCities 所有城池
*/
export function getCities(guildCode: string, dbCities: GuildActivityCityType[]) {
let cities = new Array<CityParam>();
for (let [cityId, dic] of gameData.cityActivity) {
let param = new CityParam(cityId);
let curCity = dbCities.find(cur => cur.cityId == cityId);
if (curCity) {
param.guardGuildCode = curCity.guardGuildCode || "";
param.guardGuildName = curCity.guardGuildName || "";
param.declareCount = curCity.declareCount || 0;
}
param.status = getCityStatus(guildCode, cityId, dic, dbCities);
cities.push(param);
}
return cities
}
/**
* 诸侯混战 获取城池状态
* @param guildCode
* @param cityId
* @param dic
* @param dbCities
*/
export function getCityStatus(guildCode: string, cityId: number, dic: DicCityActivity, dbCities: GuildActivityCityType[]) {
let status = CITY_STATUS.NOT_OPEN;
let d = getCurDay(true);
let { week, preCity } = dic;
let activityStatus = getGuildActivityStatus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);
if (!activityStatus) {
return CITY_STATUS.NOT_OPEN
}
let dicGuildActivity = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);
let { openDay } = dicGuildActivity;
let curIndex = openDay.indexOf(week[0]);
let startDay = openDay[curIndex - 1] || 0;
let endDay = openDay[openDay.length - 1] || 0;
if (d >= startDay && d <= endDay) status = CITY_STATUS.CAN_DECLARE;
if (d == startDay && activityStatus.status != GUILD_ACTIVITY_STATUS.END) status = CITY_STATUS.NOT_OPEN;
if (d == endDay && activityStatus.status == GUILD_ACTIVITY_STATUS.END) status = CITY_STATUS.NOT_OPEN;
let curCity = dbCities.find(cur => cur.cityId == cityId);
if (curCity) {
if (curCity.guardGuildCode == guildCode) {
status = CITY_STATUS.GUARD;
} else if (curCity.declareGuilds.includes(guildCode)) {
status = CITY_STATUS.DECLARED;
}
}
// let hasGuard = false, hasDeclared = false;
// for(let { cityId: _cityId, guardGuildCode, declareGuilds } of dbCities) {
// let dicCity = gameData.cityActivity.get(_cityId);
// if(dicCity.type == dic.type) {
// if(guardGuildCode == guildCode) hasGuard = true;
// if(declareGuilds.includes(guildCode)) hasDeclared = true;
// }
// }
// if(status == CITY_STATUS.CAN_DECLARE && !hasDeclared && preCity.length > 0) {
// status = CITY_STATUS.NOT_OPEN;
// }
return status;
}
export async function sendGuildCityDeclare(cityId: number, declareGuildCode: string, declareCount: number) {
let msg = { cityId, declareGuildCode, declareCount };
await sendMessageToCityWithSuc(cityId, PUSH_ROUTE.GUILD_CITY_DECLARE, msg);
await sendMessageToGuildWithSuc(declareGuildCode, PUSH_ROUTE.GUILD_CITY_DECLARE, msg);
}
/**
* 每秒计算木牛流马状态并下发
* @param serverId 区id
*/
export async function calWoodenHorseAndSend(serverId: number) {
console.log('calWoodenHorseAndSend');
let obj = getRaceActivityObj();
let { guildRank: ranks } = await obj.getRanks(serverId);
let map = new Map<number, WoodenHorse[]>();
// 找到往前和往后2艘船
for (let i = 0; i < ranks.length; i++) {
let { code } = ranks[i];
for (let j = i; j <= i + 2; j++) {
if (j <= ranks.length - 1 && !map.has(j)) {
map.set(j, new Array<WoodenHorse>());
}
}
for (let [rank, woodenHorseList] of map) {
let limit = 5;
if (rank - 2 < 0) limit += rank - 2;
if (rank + 2 > ranks.length - 1) limit -= (rank + 2) - (ranks.length - 1);
let woodenHorse = await obj.getWoodenHorse(code, serverId);
if (!!woodenHorse) {
map.get(rank).push(woodenHorse);
} else {
limit--; // 理论上不能出现没有woodenHorse的情况但是如果出现了以防无返回
}
let len = map.get(rank).length;
if (len >= limit) {
// 发送
// console.log('send', woodenHorseList.length);
let curRank = ranks[rank];
let wh = await obj.getWoodenHorse(curRank.code, serverId);
let events = obj.getEvents(curRank.code, wh ? wh.distance : 0);
await sendMessageToGuildWithSuc(curRank.code, PUSH_ROUTE.GUILD_RACE_UPDATE, { timestamp: Date.now(), woodenHorseList: woodenHorseList.filter(cur => cur.status != RACE_ACTIVITY_STATUS.END), guildRank: ranks, myGuildRank: curRank, events });
map.delete(rank);
}
}
}
return;
}
/**
* 木牛流马活动开始信号
*/
export async function sendRaceStartMsg(serverId: number) {
let obj = getRaceActivityObj();
obj.startRace(); // 设置开启活动
await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.RACE_START, {});
await calWoodenHorseAndSend(serverId);
}
export async function cityActivityStart() {
let obj = getCityActivityObj();
obj.startActivity();
}
export async function gateActivityStart() {
let obj = getGateActivityObj();
obj.startActivity();
}
/**
* 结算粮草先行奖励
* @param cityId 城镇id
* @param serverId 服务器id
*/
export async function raceActivitySettleReward(guildCode: string, woodenHorse: WoodenHorse) {
let { serverId, durability, distance } = woodenHorse;
let obj = getRaceActivityObj();
// 计算排名,计算耐久,发送奖励
let { guildRank, myGuildRank } = await obj.getRanks(serverId, guildCode);
let rank = myGuildRank?.rank||0;
let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId });
await r.setRankWithGuildInfo2(guildCode, myGuildRank.num, myGuildRank.sortTime, myGuildRank.durability);
let tomorrow = <number>getTimeFun().getAfterDayWithHour();
await r.setExpire(tomorrow);
let isSuccess = distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH; // 血条未击破则没有占领军团
let members = obj.getMembersOfGuild(guildCode);
let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, rank);
let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, {
memberCnt: members.length, members,
isSuccess, isCompleted: true, rank,
rewards: rewards.map(cur => cur.goods),
woodenHorse: woodenHorse.getTreatTime(),
});
if (rec) {
// 奖励加入拍卖行
await genAuction(guildCode, AUCTION_SOURCE.RACE, rec.code, serverId, rewards);
let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY);
let honour = dic.honour + Math.floor(durability * GUILDACTIVITY.RACEACTIVITY_DURABILITY_REWARD);
let hasSentMember: string[] = [];
for(let { roleId } of members) {
if(hasSentMember.indexOf(roleId) == -1) {
await updateUserRecAndSendHonour(honour, 0, rank, roleId);
// 发放活跃
await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值
hasSentMember.push(roleId);
}
}
}
// 删除数据
obj.deleteFromList(guildCode);
}
/**
* !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用
* 改变字典表中的军团活动开始时间&持续时间
* @param {number} aid 活动
* @param {number} startSeconds 从现在开始几秒后开启活动
* @param {number} endSeconds 从开始之后几秒后结束活动
*/
export async function setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) {
let startTime = new Date(now + startSeconds * 1000);
if(aid != 0) {
let guildActivity = gameData.guildActivity;
let cur = guildActivity.get(aid);
cur.startMinute = startTime.getMinutes();
cur.startTime = startTime.getHours();
cur.startSeconds = startTime.getSeconds();
cur.duringTime = endSeconds;
}
return startTime.getTime();
}
export async function setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) {
// console.log('********* setDicAuctionTime', startTime, endActivity, startGuild, endGuild, startWorld, endWorld);
let startGuildDate = new Date(startTime + endActivity * 1000 + startGuild * 1000);
let endGuildDate = new Date(startGuildDate.getTime() + endGuild * 1000);
let startWorldDate = new Date(endGuildDate.getTime() + startWorld * 1000);
let endWorldDate = new Date(startWorldDate.getTime() + endWorld * 1000);
// console.log('********* setDicAuctionTime', startGuildDate, endGuildDate, startWorldDate, endWorldDate);
gameData.auctionTime.set(AUCTION_TIME.GUILD_PREVIEW, formatTime(new Date(startTime)));
gameData.auctionTime.set(AUCTION_TIME.GUILD_OPEN, formatTime(startGuildDate));
gameData.auctionTime.set(AUCTION_TIME.GUILD_CLOSE, formatTime(endGuildDate));
gameData.auctionTime.set(AUCTION_TIME.WORLD_PREVIEW, formatTime(endGuildDate));
gameData.auctionTime.set(AUCTION_TIME.WORLD_OPEN, formatTime(startWorldDate));
gameData.auctionTime.set(AUCTION_TIME.WORLD_CLOSE, formatTime(endWorldDate));
// console.log('*********** setDicAuctionTime', gameData.auctionTime)
}
function formatTime(date: Date) {
return { hour: date.getHours(), minute: date.getMinutes(), seconds: date.getSeconds() }
}
export async function getCityActivityGateHp(serverId: number, cityId: number) {
console.log(`getCityActivityGateHp: serverId ${serverId}, cityId ${cityId}`);
let dicCityActivity = gameData.cityActivity.get(cityId);
let serverRecord = await ServerRecordModel.findTodayData(serverId);
if(!serverRecord) return dicCityActivity.hp;
let activePlayerCnt = 1, activePlayerCe = 0, activeTopPlayerCnt = 1, activeGuildCnt = 1;
if(serverRecord) {
if(serverRecord.activePlayerCnt > 0) activePlayerCnt = serverRecord.activePlayerCnt;
if(serverRecord.activePlayerCe > 0) activePlayerCe = serverRecord.activePlayerCe;
if(serverRecord.activePlayers?.length > 0) activeTopPlayerCnt = serverRecord.activePlayers?.length;
if(serverRecord.activeGuildCodes?.length > 0) activeGuildCnt = serverRecord.activeGuildCodes?.length;
}
console.log(`getCityActivityGateHp: activePlayerCnt ${activePlayerCnt}, activePlayerCe ${activePlayerCe}, activeTopPlayerCnt ${activeTopPlayerCnt} activeGuildCnt ${activeGuildCnt}`);
let atk = dicCityActivity.atkTemplate||0;
console.log(`getCityActivityGateHp: atk ${atk}`);
let A = activePlayerCe/activeTopPlayerCnt/6/GUILDACTIVITY.GATEACTIVITY_ENEMYCE;
if(A < 1) A = 1;
console.log(`getCityActivityGateHp: A ${A}`);
let gateHpBase = A * atk;
let N = dicCityActivity.hpN;
console.log(`getCityActivityGateHp: gateHpBase ${gateHpBase}, N ${N}`);
let gateHp = Math.floor(gateHpBase * (activePlayerCnt/activeGuildCnt) * N);
console.log(`getCityActivityGateHp: gateHp ${gateHp}`);
if(gateHp <= dicCityActivity.hp) {
gateHp = dicCityActivity.hp;
}
return gateHp;
}