// 军团活动蛮夷入侵城门血量等数据存储 import { Member, GateMembersRec, WoodenHorse, Event, WoodenHorseMember } 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 } from "../../consts"; import { getGuildChannelSid } from "../chatService"; import { pinus } from "pinus"; import { getRandEelm, sortArrRandom, resResult, getRandResultByMember } from "../../pubUtils/util"; import { Rank } from "../rankService"; import { getTimeFun } from "../../pubUtils/timeUtil"; import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../pushService"; // 粮草先行 export class RaceActivityObject { private status = RACE_ACTIVITY_STATUS.WAITING; // 活动状态 0-未开始 1-已开始 2-已结束 public guildList: Array<{ serverId: number, guildCode: string }> = []; // 所有军团 private members: Map> = new Map(); // 每个军团参与的成员 guildCode => [{roleId, job}] private woodenHorses: Map = new Map(); // 每个军团的木牛流马 guildCode => WoodenHorse private events: Map = new Map(); // 每个军团遇到的事件 private items: Map = 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 joinWoodenHorse(guildCode: string, roleId: string, roleName: string, serverId: number, sid: string, job: number, code: string) { let woodenHorse = await this.getWoodenHorse(guildCode, serverId); 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) { if(!this.woodenHorses.has(guildCode)) { this.initEvents(guildCode); let guild = await GuildModel.findByCode(guildCode, serverId); if(!guild) return false; let { name: guildName, guildCe } = guild; this.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildName, guildCe, serverId)); this.guildList.push({guildCode, serverId}); } let woodenHorse = this.woodenHorses.get(guildCode); let events = this.events.get(guildCode)||[]; let needSendEnd = woodenHorse.calCurWoodenHorse(events); if(woodenHorse.status == RACE_ACTIVITY_STATUS.START || woodenHorse.status == RACE_ACTIVITY_STATUS.END) { // 更新距离 let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 5); await r.setRank({guildCode}, [Math.floor(woodenHorse.distance * 1000), woodenHorse.time], false); let tomorrow = getTimeFun().getAfterDayWithHour(); await r.setExpire(tomorrow); if (needSendEnd) { // 抵达后发送奖励,发送消息,结算 await sendSingleRaceActEndMsg(guildCode, woodenHorse); } } this.handleItemsByWoodenHorse(woodenHorse); return woodenHorse; } public async useItem(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); } await sendMessageToGuildWithSuc(toGuild, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] }); return event; } // 定时任务到,开始比赛,设置开始赛道,发放初始道具 public startRace() { this.status = RACE_ACTIVITY_STATUS.START; let guildCodes = new Array(); for(let [code, woodenHorse] of this.woodenHorses) { if(woodenHorse.memberCnt > 0) { this.woodenHorseStartRace(woodenHorse); guildCodes.push(code); } } return guildCodes; } private woodenHorseStartRace(woodenHorse: WoodenHorse) { woodenHorse.status = RACE_ACTIVITY_STATUS.START; woodenHorse.time = Date.now(); woodenHorse.startTime = Date.now(); let members = woodenHorse.members; let normalItems = getRaceEventItems(); this.sendRandItemsToMembers(members, woodenHorse, normalItems); } private sendRandItemsToMembers(members: WoodenHorseMember[], woodenHorse: WoodenHorse, items: Map) { let notReceiveMembers = members.filter(member => !member.isReceived()); let memberCnt = notReceiveMembers.length; let addItems: Map = 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(); 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; } }