336 lines
14 KiB
TypeScript
336 lines
14 KiB
TypeScript
|
||
// 军团活动蛮夷入侵城门血量等数据存储
|
||
|
||
import { Member, GateMembersRec, WoodenHorse, Event, WoodenHorseMember, RaceActivityRankParam } from "../../domain/battleField/guildActivity";
|
||
import { RewardInter } from "../../pubUtils/interface";
|
||
import { getRaceEventItems, gameData } from "../../pubUtils/data";
|
||
import { GuildModel } from "../../db/Guild";
|
||
import { sendSingleRaceActEndMsg } from "./guildActivityService";
|
||
import { REDIS_KEY, RACE_EVENT_TYPE, RACE_EVENT_EFFECT_TYPE, RACE_EVENT, STATUS, RACE_ACTIVITY_STATUS, PUSH_ROUTE, GUILD_ACTIVITY_STATUS, DEBUG_MAGIC_WORD } from "../../consts";
|
||
import { getRandEelm, sortArrRandom, resResult, getRandResultByMember } from "../../pubUtils/util";
|
||
import { sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToUserWithSuc } from "../pushService";
|
||
|
||
// 粮草先行
|
||
export class RaceActivityObject {
|
||
public status = RACE_ACTIVITY_STATUS.WAITING; // 活动状态 0-未开始 1-已开始 2-已结束
|
||
private allStartTime = 0; // 开启时间,每天晚上8点
|
||
public guildList: Array<{ serverId: number, guildCode: string }> = []; // 所有军团
|
||
private members: Map<string, Array<Member>> = new Map(); // 每个军团参与的成员 guildCode => [{roleId, job}]
|
||
private woodenHorses: Map<string, WoodenHorse> = new Map(); // 每个军团的木牛流马 guildCode => WoodenHorse
|
||
private events: Map<string, Event[]> = new Map(); // 每个军团遇到的事件
|
||
private items: Map<string, RewardInter[]> = new Map(); // 每个玩家的道具 roleId => [{id, count}]
|
||
private hasSentGuild: string[] = [];
|
||
|
||
public getItem(roleId: string) {
|
||
return this.items.get(roleId)||[]
|
||
}
|
||
|
||
// 是否加入过
|
||
public getMember(guildCode: string, roleId: string) {
|
||
let member = this.members.get(guildCode)||[];
|
||
return member.find(cur => cur.roleId == roleId);
|
||
}
|
||
|
||
// 加入member
|
||
private pushMember(guildCode: string, roleId: string, job: number, code: string) {
|
||
if(!this.members.has(guildCode)) {
|
||
this.members.set(guildCode, []);
|
||
}
|
||
this.members.get(guildCode).push({roleId, job, code});
|
||
}
|
||
|
||
public getMembersOfGuild(guildCode: string) {
|
||
return this.members.get(guildCode)||[];
|
||
}
|
||
|
||
public getAllWoodenHorses() {
|
||
return this.woodenHorses;
|
||
}
|
||
|
||
public async getRanks(serverId: number, guildCode?: string) {
|
||
let myRank: RaceActivityRankParam = null;
|
||
let ranks: RaceActivityRankParam[] = [];
|
||
let myIndex = -1;
|
||
for(let [_, _wh] of this.woodenHorses) {
|
||
if(_wh.serverId == serverId && _wh.status != GUILD_ACTIVITY_STATUS.WAITING) {
|
||
let wh = await this.getWoodenHorse(_wh.guildCode, _wh.serverId);
|
||
if(wh) {
|
||
ranks.push(new RaceActivityRankParam(wh));
|
||
}
|
||
}
|
||
}
|
||
ranks.sort((a, b) => {
|
||
if(a.sortDistance == b.sortDistance) {
|
||
return a.sortTime - b.sortTime;
|
||
} else {
|
||
return b.sortDistance - a.sortDistance;
|
||
}
|
||
}).map((wh, index) => {
|
||
wh.setRank(index + 1);
|
||
if(guildCode && wh.code == guildCode) {
|
||
myRank = wh;
|
||
myIndex = index;
|
||
}
|
||
return wh
|
||
});
|
||
|
||
if(!myRank && guildCode) {
|
||
let myWoodenHorse = await this.getWoodenHorse(guildCode, serverId);
|
||
if(myWoodenHorse) myRank = new RaceActivityRankParam(myWoodenHorse);
|
||
}
|
||
|
||
return { guildRank: ranks, myGuildRank: myRank, myIndex }
|
||
}
|
||
|
||
public async joinWoodenHorse(guildCode: string, roleId: string, roleName: string, serverId: number, sid: string, job: number, code: string, isDebug = false) {
|
||
let woodenHorse = await this.getWoodenHorse(guildCode, serverId, isDebug);
|
||
if(!woodenHorse) return false;
|
||
let member = woodenHorse.joinMember(roleId, roleName, sid, code)
|
||
this.pushMember(guildCode, roleId, job, code);
|
||
|
||
if(this.status == RACE_ACTIVITY_STATUS.START) {
|
||
this.sendRandItemsToMembers([member], woodenHorse, woodenHorse.remainItems);
|
||
this.woodenHorseStartRace(woodenHorse);
|
||
}
|
||
return await this.getWoodenHorse(guildCode, serverId);
|
||
}
|
||
|
||
// 获取某个军团的木马状态
|
||
public async getWoodenHorse(guildCode: string, serverId: number, isDebug: boolean = false) {
|
||
if(!this.woodenHorses.has(guildCode)) {
|
||
this.initEvents(guildCode);
|
||
if(isDebug) {
|
||
this.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildCode, 0, serverId, this.allStartTime, false));
|
||
this.guildList.push({guildCode, serverId});
|
||
} else {
|
||
let guild = await GuildModel.findByCode(guildCode, serverId);
|
||
if(!guild) return undefined;
|
||
let { name: guildName, guildCe } = guild;
|
||
this.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildName, guildCe, serverId, this.allStartTime, false));
|
||
this.guildList.push({guildCode, serverId});
|
||
}
|
||
}
|
||
let woodenHorse = this.woodenHorses.get(guildCode);
|
||
let events = this.events.get(guildCode)||[];
|
||
let needSendEnd = woodenHorse.calCurWoodenHorse(events);
|
||
if (needSendEnd) { // 抵达后发送奖励,发送消息,结算
|
||
await sendSingleRaceActEndMsg(guildCode, woodenHorse);
|
||
}
|
||
|
||
this.handleItemsByWoodenHorse(woodenHorse);
|
||
return woodenHorse;
|
||
}
|
||
|
||
public async useItem(serverId: number, fromRoleId: string, sid: string, fromGuild: string, toGuild: string, id: number, count: number) {
|
||
let rec = this.handleItems(fromRoleId, sid, [{id, count: -1 * count}]);
|
||
if(!rec) return false;
|
||
let event = new Event(id, fromGuild, toGuild, count);
|
||
if(!this.events.has(toGuild)) {
|
||
this.events.set(toGuild, [event]);
|
||
} else {
|
||
let events = this.events.get(toGuild)||[];
|
||
events.push(event);
|
||
this.events.set(toGuild, events);
|
||
}
|
||
let { guildRank, myGuildRank, myIndex } = await this.getRanks(serverId, toGuild);
|
||
if(myGuildRank) {
|
||
let ranks = this.getScreenHorseRanks(guildRank, myIndex);
|
||
for(let rank of ranks||[]) {
|
||
if(rank) await sendMessageToGuildWithSuc(rank.code, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] });
|
||
}
|
||
let timeout = setTimeout(async () => {
|
||
await this.getScreenHorses(serverId, guildRank, myIndex, true);
|
||
clearTimeout(timeout);
|
||
}, event.startTime - Date.now())
|
||
} else {
|
||
await sendMessageToGuildWithSuc(toGuild, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] });
|
||
}
|
||
return event;
|
||
}
|
||
|
||
// 定时任务到,开始比赛,设置开始赛道,发放初始道具
|
||
public startRace() {
|
||
this.status = RACE_ACTIVITY_STATUS.START;
|
||
if(this.allStartTime == 0) this.allStartTime = Date.now();
|
||
let guildCodes = new Array<string>();
|
||
for(let [code, woodenHorse] of this.woodenHorses) {
|
||
if(woodenHorse.memberCnt > 0) {
|
||
this.woodenHorseStartRace(woodenHorse);
|
||
guildCodes.push(code);
|
||
}
|
||
}
|
||
return guildCodes;
|
||
}
|
||
|
||
private woodenHorseStartRace(woodenHorse: WoodenHorse) {
|
||
woodenHorse.startRace(this.allStartTime);
|
||
let members = woodenHorse.members;
|
||
let normalItems = getRaceEventItems();
|
||
this.sendRandItemsToMembers(members, woodenHorse, normalItems);
|
||
}
|
||
|
||
private sendRandItemsToMembers(members: WoodenHorseMember[], woodenHorse: WoodenHorse, items: Map<number, { total: number, max: number}>) {
|
||
let notReceiveMembers = members.filter(member => !member.isReceived());
|
||
let memberCnt = notReceiveMembers.length;
|
||
let addItems: Map<string, { member: WoodenHorseMember, items: {id: number, count: number}[] }> = new Map();
|
||
for(let [id, {total, max}] of items) {
|
||
let randResult = getRandResultByMember(total, max, memberCnt);
|
||
for(let i = 0; i < memberCnt; i++) {
|
||
let member = notReceiveMembers[i];
|
||
let count = randResult.arr[i]||0;
|
||
if(count > 0) {
|
||
if(!addItems.has(member.roleId)) {
|
||
addItems.set(member.roleId, { member: member, items: [] });
|
||
}
|
||
addItems.get(member.roleId).items.push({ id, count });
|
||
}
|
||
}
|
||
woodenHorse.setRemainItem(id, randResult.remain, max);
|
||
}
|
||
for(let [_roleId, {member, items}] of addItems) {
|
||
member.setReceived(true);
|
||
this.handleItems(member.roleId, member.sid, items);
|
||
}
|
||
}
|
||
|
||
// 初始进入就随机9个灵球事件
|
||
public initEvents(guildCode: string) {
|
||
if(!this.events.get(guildCode)) {
|
||
this.events.set(guildCode, []);
|
||
}
|
||
let dicEncounter = gameData.raceActivityEncounter; // 距离=>事件类型
|
||
let goodEventNum = Math.floor(dicEncounter.eventNum/2);
|
||
let badEventNum = dicEncounter.eventNum - goodEventNum;
|
||
|
||
let dicRaceTypes = gameData.raceTypes.get(RACE_EVENT_TYPE.EVENT);
|
||
let goodEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.GOOD), goodEventNum);
|
||
let badEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.BAD), badEventNum);
|
||
let events = sortArrRandom(goodEvents.concat(badEvents));
|
||
let index = 0;
|
||
|
||
for(let [distance, type] of dicEncounter.events) {
|
||
if(type == RACE_EVENT_TYPE.ITEM) {
|
||
let event = new Event(RACE_EVENT.ITEM, guildCode, guildCode, 1, distance);
|
||
this.events.get(guildCode).push(event);
|
||
} else if (type == RACE_EVENT_TYPE.EVENT) {
|
||
let event = new Event(events[index], guildCode, guildCode, 1, distance);
|
||
this.events.get(guildCode).push(event);
|
||
index ++;
|
||
}
|
||
}
|
||
}
|
||
|
||
public getEvents(guildCode: string, distance: number) {
|
||
let events = this.events.get(guildCode)||[];
|
||
let result = new Array<Event>();
|
||
for(let event of events) {
|
||
let { endTime, endDistance } = event;
|
||
if(endTime) {
|
||
if(Date.now() > endTime) continue;
|
||
}
|
||
if(endDistance) {
|
||
if(distance > endDistance) continue;
|
||
}
|
||
result.push(event);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
private handleItemsByWoodenHorse(woodenHorse: WoodenHorse) {
|
||
let { members } = woodenHorse;
|
||
for(let curMember of members) {
|
||
let { roleId, sid, items = [] } = curMember;
|
||
if(items.length > 0) this.handleItems(roleId, sid, items);
|
||
curMember.items = [];
|
||
}
|
||
}
|
||
|
||
private handleItems(roleId: string, sid: string, incItems: {id: number, count: number}[]) {
|
||
let items = this.items.get(roleId)||[];
|
||
let sendItems = new Array<{id: number, count: number}>();
|
||
for(let {id, count: inc} of incItems) {
|
||
let curItem = items.find(cur => cur.id == id);
|
||
if(!curItem) {
|
||
curItem = { id, count: 0 };
|
||
items.push(curItem);
|
||
}
|
||
if(curItem.count + inc < 0 ) return false;
|
||
if(inc != 0) {
|
||
curItem.count += inc;
|
||
sendItems.push({ id, count: curItem.count });
|
||
}
|
||
}
|
||
this.items.set(roleId, items);
|
||
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.RACE_ITEM_UPDATE, { items: sendItems }, sid);
|
||
return items;
|
||
}
|
||
|
||
public deleteFromList(guildCode: string) {
|
||
this.hasSentGuild.push(guildCode);
|
||
}
|
||
|
||
public hasSend(guildCode: string) {
|
||
return this.hasSentGuild.indexOf(guildCode) != -1;
|
||
}
|
||
|
||
public async calServerHorses(serverId: number) {
|
||
let { guildRank: ranks } = await this.getRanks(serverId);
|
||
// 找到往前和往后2艘船
|
||
for (let i = 0; i < ranks.length; i++) {
|
||
await this.getScreenHorses(serverId, ranks, i, true);
|
||
}
|
||
|
||
}
|
||
|
||
private getScreenHorseRanks(ranks: RaceActivityRankParam[], i: number) {
|
||
let curRank = ranks[i];
|
||
if(!curRank || curRank.durability == 0) return;
|
||
|
||
let beforeHorses: RaceActivityRankParam[] = [], afterHorses: RaceActivityRankParam[] = [], beforeCnt = 0, afterCnt = 0;
|
||
for(let j = i - 1; j >= 0; j--) {
|
||
if(ranks[j]) {
|
||
beforeHorses.push(ranks[j]);
|
||
if(ranks[j].durability > 0) beforeCnt ++
|
||
}
|
||
if(beforeCnt >= 2) break;
|
||
}
|
||
for(let j = i + 1; j < ranks.length; j++) {
|
||
if(ranks[j]) {
|
||
afterHorses.push(ranks[j]);
|
||
if(ranks[j].durability > 0) afterCnt++;
|
||
}
|
||
if(afterCnt >= 2) break;
|
||
}
|
||
// 发送
|
||
// console.log('send', woodenHorseList.length);
|
||
return [...beforeHorses.reverse(), curRank, ...afterHorses]
|
||
}
|
||
|
||
private async getScreenHorses(serverId: number, ranks: RaceActivityRankParam[], i: number, needSend: boolean) {
|
||
let curRank = ranks[i];
|
||
if(!curRank) return;
|
||
// 发送
|
||
// console.log('send', woodenHorseList.length);
|
||
let wh = await this.getWoodenHorse(curRank.code, serverId);
|
||
let screenRank = this.getScreenHorseRanks(ranks, i);
|
||
let woodenHorseList: WoodenHorse[] = [];
|
||
if(curRank.durability != 0) {
|
||
for(let rank of screenRank) {
|
||
if(rank.code == curRank.code) {
|
||
woodenHorseList.push(wh);
|
||
} else {
|
||
let wh = await this.getWoodenHorse(rank.code, serverId);
|
||
woodenHorseList.push(wh);
|
||
}
|
||
}
|
||
}
|
||
|
||
if(needSend) {
|
||
let events = this.getEvents(curRank.code, wh ? wh.distance : 0);
|
||
await sendMessageToGuildWithSuc(curRank.code, PUSH_ROUTE.GUILD_RACE_UPDATE, { timestamp: Date.now(), woodenHorseList, guildRank: ranks, myGuildRank: curRank, events });
|
||
}
|
||
return woodenHorseList
|
||
}
|
||
}
|
||
|