diff --git a/game-server/app/services/guildActivity/raceActivityObj.ts b/game-server/app/services/guildActivity/raceActivityObj.ts index b0c66869a..838f75fe4 100644 --- a/game-server/app/services/guildActivity/raceActivityObj.ts +++ b/game-server/app/services/guildActivity/raceActivityObj.ts @@ -1,7 +1,7 @@ // 军团活动蛮夷入侵城门血量等数据存储 -import { Member, GateMembersRec, WoodenHorse, Event } from "../../domain/battleField/guildActivity"; +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"; @@ -9,7 +9,7 @@ import { sendSingleRaceActEndMsg } from "./guildActivityService"; import { REDIS_KEY, RACE_EVENT_TYPE, RACE_EVENT_EFFECT_TYPE, RACE_EVENT, STATUS, RACE_ACTIVITY_STATUS } from "../../consts"; import { getGuildChannelSid } from "../chatService"; import { pinus } from "pinus"; -import { getRandEelm, sortArrRandom, resResult } from "../../pubUtils/util"; +import { getRandEelm, sortArrRandom, resResult, getRandResultByMember } from "../../pubUtils/util"; import { Rank } from "../rankService"; import { getTimeFun } from "../../pubUtils/timeUtil"; @@ -52,12 +52,11 @@ export class RaceActivityObject { 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; - woodenHorse.joinMember(roleId, roleName, sid, code) + let member = woodenHorse.joinMember(roleId, roleName, sid, code) this.pushMember(guildCode, roleId, job, code); if(this.status == RACE_ACTIVITY_STATUS.START) { - let item = getRaceEventItems(); - this.handleItems(roleId, sid, item); + this.sendRandItemsToMembers([member], woodenHorse, woodenHorse.remainItems); this.woodenHorseStartRace(woodenHorse); } return await this.getWoodenHorse(guildCode, serverId); @@ -126,9 +125,31 @@ export class RaceActivityObject { woodenHorse.time = Date.now(); woodenHorse.startTime = Date.now(); let members = woodenHorse.members; - for(let { roleId, sid } of members) { - let item = getRaceEventItems(); - this.handleItems(roleId, sid, item); + 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); } } diff --git a/shared/domain/battleField/guildActivity.ts b/shared/domain/battleField/guildActivity.ts index 92c446ba5..ce50b643c 100644 --- a/shared/domain/battleField/guildActivity.ts +++ b/shared/domain/battleField/guildActivity.ts @@ -3,7 +3,7 @@ import { SimpleGuildRankParam, SimpleRoleRankParam } from '../rank' import { prop } from "@typegoose/typegoose"; import { CITY_STATUS, RACE_ACTIVITY_STATUS, RACE_EVENT } from "../../consts"; import { gameData, getRaceEventItems } from "../../pubUtils/data"; -import { getRandEelm } from "../../pubUtils/util"; +import { getRandEelm, getRandResultByMember, getRandValueByMinMax, sortArrRandom } from "../../pubUtils/util"; import { RewardInter } from "../../pubUtils/interface"; export class GateMembersRec { @@ -15,13 +15,46 @@ export class GateMembersRec { } } -class WoodenHorseMember { +export class WoodenHorseMember { roleId: string; roleName: string; sid: string; - items?: RewardInter[]; + items: RewardInter[] = []; code?: string; + hasReceiveInitItems: boolean = false; + constructor(roleId: string, roleName: string, sid: string, code: string) { + this.roleId = roleId; + this.roleName = roleName; + this.sid = sid; + this.code = code; + } + + addTempItem(item: RewardInter) { + this.items.push(item); + } + + addTempItems(items: RewardInter[]) { + this.items.push(...items); + } + + getTempItems() { + return this.items; + } + + receiveTempItems() { + let items = [...this.items]; + this.items = []; + return items; + } + + isReceived() { + return this.hasReceiveInitItems; + } + + setReceived(hasReceiveInitItems: boolean) { + this.hasReceiveInitItems = hasReceiveInitItems; + } } // 木牛流马 @@ -57,6 +90,8 @@ export class WoodenHorse { @prop({required: true}) stopContinueTime: number = 0; // 鬼手阴符 + remainItems: Map = new Map(); + constructor(guildCode: string, guildName: string, guildCe: number, serverId: number) { this.guildCode = guildCode; this.guildName = guildName; @@ -178,13 +213,20 @@ export class WoodenHorse { case RACE_EVENT.ITEM: let ranMember: WoodenHorseMember[] = getRandEelm(this.members, GUILDACTIVITY.RACEACTIVITY_EVENT_MEMBERCNT); if(ranMember.length <= 0) ranMember = this.members; - for(let obj of ranMember) { + for(let member of ranMember) { let item = gameData.raceEventItems; - obj.items = (obj.items||[]).concat(item); + member.addTempItems(item); } - for(let obj of this.members) { - let item = getRaceEventItems(); - obj.items = (obj.items||[]).concat(item); + let normalItems = getRaceEventItems(); + for(let [id, {total, max}] of normalItems) { + let randResult = getRandResultByMember(total, max, this.members.length); + for(let i = 0; i < this.members.length; i++) { + let count = randResult.arr[i]||0; + if(count > 0) { + this.members[i].addTempItem({ id, count }); + normalItems.get(id).total -= count; + } + } } break; } @@ -192,14 +234,21 @@ export class WoodenHorse { public joinMember(roleId: string, roleName: string, sid: string, code: string) { - if(this.members.findIndex(cur => cur.roleId == roleId) == -1) { - this.members.push({ roleId, roleName, sid, code }); + let index = this.members.findIndex(cur => cur.roleId == roleId) + if(index == -1) { + let member = new WoodenHorseMember(roleId, roleName, sid, code); + this.members.push(member); this.speed++; this.memberCnt++; + return member; + } else { + return this.members[index]; } - return this; } + public setRemainItem(id: number, remain: number, max: number) { + this.remainItems.set(id, { total: remain, max }); + } } export class Event { diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index 5792c801a..18a1f9197 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -60,7 +60,7 @@ import { dicCityActivityReward, loadCityActivityReward } from "./dictionary/DicC import { dicRaceActivity, dicRaceTypes, loadRaceActivity } from './dictionary/DicRaceActivity'; import { GUILDACTIVITY, RECRUIT } from "./dicParam"; import * as param from "./dicParam"; -import { decodeIdCntArrayStr, parseGoodStr, decodeArrayListStr, getRandValueByMinMax, getRandEelm, readTsFile, getRandEelmWithWeight } from "./util"; +import { decodeIdCntArrayStr, parseGoodStr, decodeArrayListStr, getRandEelm, readTsFile, getRandEelmWithWeight } from "./util"; import { RACE_EVENT_TYPE } from "../consts"; import { dicShop, dicShopItem, loadShop } from "./dictionary/DicShop"; import { dicShopList, loadShopList } from "./dictionary/DicShopList"; @@ -187,7 +187,7 @@ export const gameData = { raceActivityEvents: dicRaceActivity, raceTypes: dicRaceTypes, raceActivityEncounter: { events: new Map(), eventNum: 0 }, - raceNormalItems: new Array<{id: number, min: number, max: number}>(), + raceNormalItems: new Array<{id: number, total: number, max: number}>(), raceEventItems: new Array<{id: number, count: number}>(), shop: dicShop, shopItem: dicShopItem, @@ -617,14 +617,14 @@ function decodeRaceActivityEncounter() { function decodeRaceNormalItems() { let str = GUILDACTIVITY.RACEACTIVITY_NORMAL_ITEMS; - let result = new Array<{ id: number, min: number, max: number }>(); + let result = new Array<{ id: number, total: number, max: number }>(); if (!str) return result; let decodeArr = decodeArrayListStr(str); - for (let [id, min, max] of decodeArr) { - if (isNaN(parseInt(id)) || isNaN(parseInt(min)) || isNaN(parseInt(max))) { + for (let [id, total, max] of decodeArr) { + if (isNaN(parseInt(id)) || isNaN(parseInt(total)) || isNaN(parseInt(max))) { throw new Error('data table format wrong'); } - result.push({ id: parseInt(id), min: parseInt(min), max: parseInt(max) }); + result.push({ id: parseInt(id), total: parseInt(total), max: parseInt(max) }); } gameData.raceNormalItems = result; } @@ -635,15 +635,22 @@ function decodeRaceEventItems() { } export function getRaceEventItems() { - let items = gameData.raceNormalItems; - let result = new Array(); - for (let { id, min, max } of items) { - let count = getRandValueByMinMax(min, max, 0); - result.push({ id, count }); + let items = new Map(); + for(let {id, total, max} of gameData.raceNormalItems) { + items.set(id, { total, max }); } - return result; + return items; } +// export function getRaceEventItems(members: WoodenHorseMember[], items: { id: number, total: number, max: number }[]) { +// let result = new Array(); +// for (let { id, min, max } of items) { +// let count = getRandValueByMinMax(min, max, 0); +// result.push({ id, count }); +// } +// return result; +// } + // 根据保底类型获得保底数量 export function getDicGachaFloor(id: number) { let map = decodeIdCntArrayStr(RECRUIT.RECRUIT_MUST, 1); diff --git a/shared/pubUtils/util.ts b/shared/pubUtils/util.ts index 98237a724..943c80d9f 100644 --- a/shared/pubUtils/util.ts +++ b/shared/pubUtils/util.ts @@ -237,8 +237,8 @@ export function getRandEelmWithWeight(randomList: * 不改变原数组长度,将内部元素打乱 * @param source */ -export function sortArrRandom(source = []) { - let arr = deepCopy(source); +export function sortArrRandom(source: T[] = []): T[] { + let arr: T[] = deepCopy(source); return arr.sort(() => { return Math.random() - 0.5; }); } @@ -752,4 +752,24 @@ export function getWarTypeName(warType: number) { case WAR_TYPE.TRY: return '试用关卡'; case WAR_TYPE.BOSS: return '演武台'; } - } \ No newline at end of file + } + + /** + * 一群人分总数固定的东西 + * @param total 总数 + * @param max 每个人能拿到的最大数量 + * @param memberCnt 人数 + */ + export function getRandResultByMember(total: number, max: number, memberCnt: number) { + let arr: number[] = []; + for(let i = 1; i <= memberCnt; i++) { + let randMax = total > max? max: total; + let randMin = total - (memberCnt - i) * max; + if(randMin < 0) randMin = 0; + if(randMin > max) randMin = max; + let rand = getRandValueByMinMax(randMin, randMax + 1, 0); + arr.push(rand); + total -= rand; + } + return { arr, remain: total } + } \ No newline at end of file