import { GIFT_PACKAGE_TYPE, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts'; import { gameData } from '../../pubUtils/data'; import { addItems } from '../role/rewardService'; import { RewardParam } from '../../domain/activityField/rewardField'; import { CreateHeroParam } from '../../domain/roleField/hero'; import { DicGiftPackage } from '../../pubUtils/dictionary/DicGiftPackage'; import { ItemInter, RewardInter } from '../../pubUtils/interface'; import { decodeArrayListStr, getRandEelmWithWeight, resResult } from '../../pubUtils/util'; import { createHeroes } from '../role/createHero'; import { GuildModel } from '../../db/Guild'; import { pushGuildInfoUpdate } from '../guildService'; import { combineItems } from '../role/util'; import { recordGuildFund } from './timeLimitRankService'; import { filterGoods, isGoodsHidden, isHeroHidden } from '../dataService'; import { DicGiftPackagePlan } from '../../pubUtils/dictionary/DicGiftPackagePlan'; import { Floor, GiftPackageFloorModel, GiftPackageFloorType } from '../../db/GiftPackageFloor'; import { isNumber } from 'underscore'; /** * 兑换礼包 * @param giftID 礼包id * @param roleId 角色id * @param roleName 角色名称 * @param giftCount 一共消耗多少个礼包 * @param sid */ export async function useGiftPackage(roleId: string, roleName: string, sid: string, serverId: number, guildCode: string, giftID: number, selected: Array = [], giftCount: number) { console.log("bbbbbbbb", giftID, selected) let result: { goods: {id: number, count: number, seqId?: number|string, isBag?: boolean}[], addHeros: any[]} = { goods: [], addHeros: [] } let giftPackageData = gameData.giftPackage.get(giftID); if (!giftPackageData) { return resResult(STATUS.SUCCESS, result); } console.log('dddddddddddddd', giftID, JSON.stringify(giftPackageData)) let giftType = giftPackageData.type;//礼包类型 let dicGiftPackagePlan = gameData.giftPackagePlan.get(giftPackageData.id)||[]; switch (giftType) { case GIFT_PACKAGE_TYPE.ALL://全部 { let allReward = []; for (let obj of dicGiftPackagePlan) { allReward.push({ type: obj.contentType, id: obj.content, count: obj.count * giftCount }); } result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); break; } case GIFT_PACKAGE_TYPE.SELECTED_X://手选 { let count = giftPackageData.count;//选择个数 if (selected.length != count) { break; } let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content)); let selectedReward = getSelectedReward(pool, selected) let allReward: { type: number, id: number, count: number }[] = []; for (let obj of selectedReward) { allReward.push({ type: obj.type, id: obj.id, count: obj.count * giftCount }); } let gids = allReward.filter(cur => cur.type == 2).map(cur => cur.id); if(gids.length > 0 && isGoodsHidden(...gids)) return resResult(STATUS.ITEM_IS_HIDDEN); let hids = allReward.filter(cur => cur.type == 1).map(cur => cur.id); if(hids.length > 0 && isHeroHidden(...gids)) return resResult(STATUS.HERO_IS_HIDDEN); result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); break; } case GIFT_PACKAGE_TYPE.RANDOM_X://随机 { let count = giftPackageData.count;//随机个数 let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content)); if(pool.length <= 0) return resResult(STATUS.DIC_DATA_NOT_FOUND); let allReward: { type: number, id: number, count: number }[] = []; let giftPackage = { giftPackageId: giftID }; const floorPlans = groupByFloorId(pool); let dropHistory = (floorPlans && Object.keys(floorPlans).length > 0) ? await GiftPackageFloorModel.findByGiftPackageId(roleId, giftID): { floors: [], getSum: 0, allSum: 0 }; for (let i = 0; i < giftCount; i++) { let { rewards, floors } = await randomSelectedData(dropHistory, pool, roleId, giftID, count); allReward.push(...rewards); giftPackage['floors'] = floors; } await GiftPackageFloorModel.updateByGiftPackageId(roleId, giftID, { floors: dropHistory.floors, getSum: dropHistory.getSum, allSum: dropHistory.allSum }); result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); Object.assign(result, { giftPackage }); break; } case GIFT_PACKAGE_TYPE.GUILD_FUND: // 军团资金 { console.log('ccccc',guildCode, giftPackageData.count, giftCount) if(!guildCode) return resResult(STATUS.ITEM_CANNOT_RECEIVE_NO_GUILD); const guild = await GuildModel.updateInfo(guildCode, {}, { fund: giftPackageData.count * giftCount }); await pushGuildInfoUpdate(guildCode, { fund: guild.fund }); recordGuildFund(serverId, guild, giftPackageData.count * giftCount); break; } default: break; } return resResult(STATUS.SUCCESS, result); } //结算奖励的内容 export async function addReward(roleId: string, roleName: string, sid: string, serverId: number, reward: Array, reason: number) { let giftReward = rewardItemData(reward); let goodArray = giftReward.goods; let heroArray = giftReward.heroes; //兑换物品 let goods = await addItems(roleId, roleName, sid, goodArray, reason) let addHeros = []; if (heroArray.length > 0) { let heroResult = await createHeroes(roleId, roleName, sid, serverId, heroArray); goods = goods.concat(heroResult.goods) addHeros = addHeros.concat(heroResult.heroes); } return { goods: combineItems(goods), addHeros } } //表中的奖励数据(包括礼包)转换成具体对应奖励物品的实例 export function rewardItemData(reward: Array) { let goods: Array = []; let heroes: Array = []; for (let obj of reward) { switch (obj.type) { case ACTIVITY_RESOURCES_TYPE.HERO: heroes.push({ hid: obj.id, count: obj.count }) break; case ACTIVITY_RESOURCES_TYPE.GOODS: goods.push({ id: obj.id, count: obj.count, expireTime: obj.expireTime }) break; case ACTIVITY_RESOURCES_TYPE.GIFTPACKAGE://配置成礼包会立刻兑换,配置成物品会把礼包放入背包中 let goodData = gameData.goods.get(obj.id);//礼包物品 let giftPackageData = gameData.giftPackage.get(goodData.gift);//礼包数据 let giftReward = rewardItemData(giftPackageData.reward) goods = goods.concat(giftReward.goods) heroes = heroes.concat(giftReward.heroes) break; default: break; } } return { goods, heroes } } export function getSelectedReward(plans: DicGiftPackagePlan[], selected: Array): Array { let selectedReward: Array = []; for (let i = 0; i < selected.length; i++) { let index = selected[i]; if (plans.length > index) { let { contentType, content, count } = plans[index]; selectedReward.push({ type: contentType, id: content, count }); } } return selectedReward; } // 根据是否触发保底,更新抽取次数 function updateFloorCount(floors: Floor[], maxQaulity: number, isTrigger: boolean) { for (let floor of floors) { if (!isTrigger) { floor.count++; } else { if (floor.quality <= maxQaulity) { floor.count = 0; } else { floor.count++; } } } return floors; } // 将随机池子根据保底 id 进行分组 function groupByFloorId(plans: DicGiftPackagePlan[]): { [key: number]: DicGiftPackagePlan[] } { return plans.reduce((acc, cur) => { if (cur.floorId !== 0) { if (!acc[cur.floorId]) acc[cur.floorId] = []; acc[cur.floorId].push(cur); } return acc; }, {} as { [key: number]: DicGiftPackagePlan[] }); } // 初始化用户某个礼包的保底数据 async function initFloorData(floors: Floor[], floorPlans: { [key: number]: DicGiftPackagePlan[] }) { for (let floorId in floorPlans) { let hasFloorFlag = false; for (let floor of floors) { if (floor.id === parseInt(floorId)) { hasFloorFlag = true; continue; } } if (!hasFloorFlag) { floors.push({ id: parseInt(floorId), count: 0, quality: gameData.giftPackageFloor.get(parseInt(floorId)).quality }); } } } async function randomSelectedData(dropHistory: {floors: Floor[], getSum: number, allSum: number }, pool: DicGiftPackagePlan[], roleId: string, giftPackageId: number, count: number) { let rewards: RewardParam[] = []; const floorPlans = groupByFloorId(pool); let { floors = [], getSum = 0, allSum = 0 } = dropHistory; for (let i = 0; i < count; i++) { let randResult = getRandEelmWithWeight(pool)?.dic; if (!randResult) continue; // 如果没有保底池子,直接返回 if (!floorPlans || Object.keys(floorPlans).length === 0) { rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); continue; } initFloorData(floors, floorPlans); // 检查随机结果的 id 是否在 floorPlans 中,是的话抽中保底 let flag = false; for (let floorId in floorPlans) { if (floorPlans[floorId].findIndex(cur => cur.id === randResult.id) !== -1) { flag = true; break; } } // 检查是否达到了保底次数,并且记录最大品质的 floorId let maxQaulityFloorId = 0; // 最大品质的 floorId let maxQaulity = 0; for (let floor of floors) { if (floor.count + 1 >= gameData.giftPackageFloor.get(floor.id).times) { flag = true; if (gameData.giftPackageFloor.get(floor.id).quality > maxQaulity) { maxQaulityFloorId = floor.id; maxQaulity = gameData.giftPackageFloor.get(floor.id).quality; } } } // 更新抽取次数,确定要返回的物品 if (flag && maxQaulityFloorId == 0) { // 抽到了保底物品 const quality = gameData.giftPackageFloor.get(randResult.floorId).quality; rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); updateFloorCount(floors, quality, true); getSum++; console.log('got floorId a: ', randResult.floorId, quality); } else if (flag && maxQaulityFloorId > 0) { // 次数保底 let floorResult = getRandEelmWithWeight(floorPlans[maxQaulityFloorId])?.dic; if (!floorResult) continue; rewards.push({ type: floorResult.contentType, id: floorResult.content, count: floorResult.count }); updateFloorCount(floors, maxQaulity, true); getSum++; console.log('got floorId b: ', maxQaulityFloorId, maxQaulity); } else { // 未达到保底次数 rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); updateFloorCount(floors, 0, false); console.log('got floorId c: ', randResult.floorId, 0); } allSum++; } let result; result = Object.assign({}, { rewards }) if(floorPlans && Object.keys(floorPlans).length > 0) { dropHistory.floors = floors; dropHistory.getSum = getSum; dropHistory.allSum = allSum; Object.assign(result, { giftPackageId, floors }); } return result; } //数据格式转换'类型&id&数量|类型&id&数量|' ->> Array 活动奖励 export function stringToRewardParam(rewardStr: string): Array { let result = new Array<{ type: number, id: number, count: number }>(); if (!rewardStr) return result; let decodeArr = decodeArrayListStr(rewardStr); for (let [type, id, count] of decodeArr) { if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) { continue; } result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) }); } return result } //数据格式转换'类型&id&数量|类型&id&数量|' ->> Array 资源消耗 export function stringToConsumeParam(...rewardStrs: string[]) { let result = new Array<{ type: number, id: number, count: number }>(); for(let rewardStr of rewardStrs) { if(!rewardStr) continue; let decodeArr = decodeArrayListStr(rewardStr); for (let [type, id, count] of decodeArr) { if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) { throw new Error('data table format wrong'); } result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) }); } } return combineItems(result); } //数据格式转换'id&数量|id&数量|' ->> Array 老资源格式 export function stringToRewardInter(rewardStr: string): Array { let result = new Array<{ id: number, count: number }>(); if (!rewardStr) return result; let decodeArr = decodeArrayListStr(rewardStr); for (let [type, id, count] of decodeArr) { if (isNaN(parseInt(id)) || isNaN(parseInt(count))) { throw new Error('data table format wrong'); } result.push({ id: parseInt(id), count: parseInt(count) }); } return result }