/** @format */ import {ccUtils} from '../utils/ccUtils' import {Data, Mgr} from '../GameControl' import {building, idNum} from '../proto/typedef' import {GoodsConfig} from '../config/GoodsConfig' import {BaseUI} from '../ui/BaseUI' import {IRoleLevelConfig, RoleLevelConfig} from '../config/RoleLevelConfig' import {CardLevelConfig, ICardLevelConfig} from '../config/CardLevelConfig' import {RoleQualityConfig} from '../config/RoleQualityConfig' import {BuildingConfig} from '../config/BuildingConfig' import {CardSkillConfig} from '../config/CardSkillConfig' import {GOODS, PREFAB_TYPE, QUALITY_TYPE} from '../enums/Enum' import {EquipmentQualityConfig} from '../config/EquipmentQualityConfig' import {EquipmentLevelConfig, IEquipmentLevelConfig} from '../config/EquipmentLevelConfig' import {RoleConfig} from '../config/RoleConfig' import {ArmorConfig} from '../config/ArmorConfig' import {CardConsumeConfig} from '../config/CardConsumeConfig' import { ICard, ICardDebris, ICastleSkill, IEquip, IGoodShowInfo, IOperateNeed, IRole, needIdNum, } from '../interface/GlobalInterface' import {UI} from '../enums/UI' import {IRewardNty, ItemUICfg} from '../interface/UIInterface' import {ITalentConfig, TalentConfig} from '../config/TalentConfig' import FrameAnimation from '../uiutils/FrameAnimation' import {CastleSkillConfig} from '../config/CastleSkillConfig' export class GoodsManager { pools: Map goodsEndPosMap: Map = new Map() bagEndPos: cc.Vec3 qualityRoleMap: Map = new Map() sameIDRoleMap: Map = new Map() qualityEquipMap: Map = new Map() sameIDEquipMap: Map = new Map() startPoint: cc.Vec2 //开始触摸的位置 curPoint: cc.Vec2 //触摸的当前位置 moveOverstepPx: number = 30 //触摸物品后移动超过多少像素就不弹出详细信息 flyGoodsCBMap: Map = new Map() reset() { this.pools = new Map() this.goodsEndPosMap.clear() this.qualityRoleMap.clear() this.sameIDRoleMap.clear() this.qualityEquipMap.clear() this.sameIDEquipMap.clear() this.flyGoodsCBMap.clear() } getGoodsNum(ID: number) { let num = Data.user.goods.get(ID) return num ? num : 0 } setGoodsNum(ID: number, num: number) { Data.user.goods.set(ID, num) } initGoods(goods: idNum[], nodes: cc.Node[], baseUI: BaseUI) { if (goods.length != nodes.length) cc.error('initGoods失败,goods数量和nodes数量不一致') for (let i = 0; i < goods.length; i++) { let parent = nodes[i] if (goods[i] && parent) this.initOneGoods(goods[i], parent, baseUI) } } detailsTouchStart(flag, event) { this.startPoint = event.getLocation() this.curPoint = event.getLocation() //如果不移动的话当前位置会是空、所以默认给开始位置 } detailsTouchMove(flag, event) { this.curPoint = event.getLocation() } initOneGoods(goods: idNum, parent: cc.Node, baseUI: BaseUI, itemUICfg: ItemUICfg = {showDetails: true}) { let {quality, iconUrl, grade, stacking, isDebris} = this.getGoodShowInfo(goods.id) let node = Mgr.global.getItemNode(parent, PREFAB_TYPE.goods, `${goods.id}_${quality}`, baseUI) if (itemUICfg && itemUICfg.changeQuality) { quality = itemUICfg.changeQuality } node.targetOff(this) if (itemUICfg && itemUICfg.showDetails) { node.on(cc.Node.EventType.TOUCH_START, this.detailsTouchStart.bind(this, true), this) node.on(cc.Node.EventType.TOUCH_END, this.showGoodsDetails.bind(this, goods.id), this) node.on(cc.Node.EventType.TOUCH_MOVE, this.detailsTouchMove.bind(this, false), this) } ccUtils.setLabel(`${stacking ? Math.toKMBNum(goods.num) : ''}`, node, 'lb') cc.find('lb', node).active = goods.num > 0 baseUI.loadNotRefTexImg(`Public/goodsQuality/item_frame${quality}`, node, 'bg') baseUI.loadNotRefTexImg(iconUrl, node, 'icon') let gradeNode = cc.find('grade', node) if (gradeNode) { gradeNode.active = grade > 0 if (grade > 0) { baseUI.loadNotRefTexImg(`Public/role/grade_${quality}`, node, 'grade') ccUtils.setLabel(grade.toString(), node, 'grade/lv') } } let debris = cc.find('debris', node) if (debris) { debris.active = isDebris } } showGoodsDetails(goodID: number) { let isXOverstep = Math.abs(this.curPoint.x - this.startPoint.x) <= this.moveOverstepPx let isYOverstep = Math.abs(this.curPoint.y - this.startPoint.y) <= this.moveOverstepPx if (isXOverstep && isYOverstep) { Mgr.ui.show(UI.ItemDetailsUI, this.getGoodShowInfo(goodID)) } } async showRectAni(item, showQuality: number, baseUI: BaseUI) { let rectAni = cc.find('rectAni', item) if (!rectAni) return let quality = 'light' let show = true if (showQuality > 1 && showQuality < 100) { quality = showQuality.toString() } else if (showQuality > 100) { let showInfo = this.getGoodShowInfo(showQuality) quality = showInfo.quality.toString() show = [PREFAB_TYPE.card, PREFAB_TYPE.equip, PREFAB_TYPE.role].includes(showInfo.goodType) } let sa = await baseUI.loadSync( Data.main.texBundle, `Public/goodsQuality/rectAni/goods_rect_ani_${quality}`, cc.SpriteAtlas, ) let frameAnimation = rectAni.getComponent(FrameAnimation) if (sa && cc.isValid(rectAni) && show) { rectAni.active = true frameAnimation.init(sa, Infinity, true) frameAnimation.play(0, true) } else { rectAni.active = false } } initNeedGoods(goods: needIdNum[], nodes: cc.Node[], baseUI: BaseUI) { for (let i = 0; i < nodes.length; i++) { let item = nodes[i] let cfg = GoodsConfig[goods[i].id] baseUI.loadNotRefTexImg(`Public/goods/${cfg.icon}`, item, 'icon') let hasNode = cc.find('has', item) ccUtils.setLabel(Math.toKMBNum(Mgr.goods.getGoodsNum(goods[i].id)), hasNode) ccUtils.setLabel(`/${Math.toKMBNum(goods[i].num)}`, item, 'need') let can = goods[i].need <= 0 hasNode.color = cc.Color.GREEN.fromHEX(can ? '#BAFF27' : '#FF2525') } } getIdNumArr(goods: number[], goodsNum: number[]) { let arr: idNum[] = [] for (let i = 0; i < goods.length; i++) { arr.push({id: goods[i], num: goodsNum[i]}) } return arr } getIdNumByCfgArr(goods: number[][]) { let arr: idNum[] = [] for (let i = 0; i < goods.length; i++) { arr.push({id: goods[i][0], num: goods[i][1]}) } return arr } /** 长数组转为idNum类型 * 传值结构:[11503, 1, 130001, 60, 110001, 10] * 返回结构:[{id:11503,num:1},{id:130001,num:60},{id:110001,num:10}] */ getLongIdNumByCfgArr(goods: number[]) { let arr: idNum[] = [] for (let i = 0; i < goods.length - 1; i += 2) { arr.push({id: goods[i], num: goods[i + 1]}) } return arr } getGoodsListByRewardNty(rewardNty: IRewardNty) { let idNumArr = [].concat(rewardNty.changeArr) for (let iCard of rewardNty.iCards) { idNumArr.push({ id: iCard.cfg.ID, num: 1, }) } for (let iRole of rewardNty.iRoles) { idNumArr.push({ id: iRole.cfg.ID, num: 1, }) } for (let iEquip of rewardNty.iEquips) { idNumArr.push({ id: iEquip.cfg.ID, num: 1, }) } for (let debris of rewardNty.debrisArr) { idNumArr.push({ id: debris.id, num: debris.num, }) } return this.getGoodsList(idNumArr) } getGoodsList(arr: idNum[]) { let newArr: idNum[] = [] for (let i = 0; i < arr.length; i++) { let idNum = arr[i] let index = newArr.findIndex( v => this.getGoodShowInfo(v.id).quality < this.getGoodShowInfo(idNum.id).quality, ) let hasIndex = newArr.findIndex(v => v.id == idNum.id) if (hasIndex == -1 && index == -1) index = newArr.length if (this.getGoodShowInfo(idNum.id).stacking) { if (hasIndex != -1) { newArr[hasIndex].num += idNum.num } else { newArr.splice(index, 0, idNum) } } else { newArr.splice(hasIndex >= 0 ? hasIndex : index, 0, ...Array(idNum.num).fill({id: idNum.id, num: 1})) } } return newArr } getGoodShowInfo(id: number): IGoodShowInfo { let quality: number let iconUrl = '' let name = '' let grade: number = 0 let stacking = false let isDebris = false let goodType: PREFAB_TYPE = null let goodsCfg = GoodsConfig[id] let roleCfg = RoleConfig[id] let cardSkillCfg = CardSkillConfig[id] let cardConsumeCfg = CardConsumeConfig[id] let armorConfig = ArmorConfig[id] if (goodsCfg) { quality = goodsCfg.quality iconUrl = `Public/goods/${goodsCfg.icon}` stacking = goodsCfg.stacking == 0 name = goodsCfg.name goodType = PREFAB_TYPE.goods } if (roleCfg) { quality = roleCfg.qualityType iconUrl = `Public/role/icon/${roleCfg.url}` grade = Data.user.gradeArr[roleCfg.quality - 1] name = roleCfg.name goodType = PREFAB_TYPE.role } if (cardSkillCfg) { quality = cardSkillCfg.qualityType iconUrl = `Public/card/icon/${cardSkillCfg.url}` grade = Data.user.gradeArr[cardSkillCfg.quality - 1] name = cardSkillCfg.name goodType = PREFAB_TYPE.card } if (cardConsumeCfg) { quality = cardConsumeCfg.qualityType iconUrl = `Public/card/icon/${cardConsumeCfg.url}` isDebris = true stacking = true name = cardConsumeCfg.name goodType = PREFAB_TYPE.cardDebris } if (armorConfig) { iconUrl = `Public/equip/icon/${armorConfig.icon}` quality = armorConfig.qualityType grade = Data.user.gradeArr[armorConfig.quality - 1] name = armorConfig.name goodType = PREFAB_TYPE.equip } return {quality, iconUrl, grade, stacking, isDebris, name, goodType, id} } getOperateNeed(idNums: idNum[]): IOperateNeed { let needArr: needIdNum[] = [] let hasGoods = true for (let goods of idNums) { let data = {id: goods.id, num: goods.num, need: goods.num - this.getGoodsNum(goods.id)} needArr.push(data) hasGoods &&= data.need <= 0 } return {need: needArr, canUp: hasGoods, isMax: false} } reactRolesChange() { this.qualityRoleMap.forEach((value, key) => { value.length = 0 }) this.sameIDRoleMap.forEach((value, key) => { value.length = 0 }) Data.user.roles.forEach(iRole => { let quality = iRole.cfg.quality if (this.roleIsUp(iRole)) return let list = this.qualityRoleMap.get(quality) let idList = this.sameIDRoleMap.get(iRole.hero.id) if (!list) { list = [] this.qualityRoleMap.set(quality, list) } list.push(iRole) if (!idList) { idList = [] this.sameIDRoleMap.set(iRole.hero.id, idList) } idList.push(iRole) }) this.sortRole() Data.user.rolesDirty = !Data.user.rolesDirty } reactCardsChange() { this.sortCard() Data.user.cardsDirty = !Data.user.cardsDirty } reactEquipsChange() { this.qualityEquipMap.forEach((value, key) => { value.length = 0 }) this.sameIDEquipMap.forEach((value, key) => { value.length = 0 }) Data.user.equips.forEach(iEquip => { let quality = iEquip.cfg.quality if (this.equipIsUp(iEquip)) return let list = this.qualityEquipMap.get(quality) let idList = this.sameIDEquipMap.get(iEquip.equip.id) if (!list) { list = [] this.qualityEquipMap.set(quality, list) } list.push(iEquip) if (!idList) { idList = [] this.sameIDEquipMap.set(iEquip.equip.id, idList) } idList.push(iEquip) }) this.sortEquip() Data.user.equipsDirty = !Data.user.equipsDirty } baseSortRule(a, b, aIndex, bIndex) { if (aIndex != bIndex) { if (aIndex >= 0 && bIndex >= 0) { //return aIndex - bIndex return b.power - a.power } else { return bIndex - aIndex } } if (a.cfg.quality != b.cfg.quality) { return b.cfg.quality - a.cfg.quality } return b.power - a.power } sortRole() { Data.user.roles.sort((a, b) => { let aIndex = Data.user.teamRole.indexOf(a) let bIndex = Data.user.teamRole.indexOf(b) return this.baseSortRule(a, b, aIndex, bIndex) }) } sortCard() { Data.user.cards.sort((a, b) => { let aIndex = Data.user.teamCard.indexOf(a) let bIndex = Data.user.teamCard.indexOf(b) return this.baseSortRule(a, b, aIndex, bIndex) }) } sortCardDebris(debris: ICardDebris[]) { debris.sort((a, b) => { return b.num - a.num }) } sortEquip() { Data.user.equips.sort((a, b) => { if (a.cfg.quality != b.cfg.quality) { return b.cfg.quality - a.cfg.quality } if (a.equip.lv != b.equip.lv) { return b.equip.lv - a.equip.lv } if (a.cfg.type != b.cfg.type) { return a.cfg.type - b.cfg.type } }) } roleIsUp(role: IRole): boolean { return role && Data.user.teamRole.findIndex(iRole => iRole && iRole.hero.sid == role.hero.sid) >= 0 } cardIsUp(card: ICard): boolean { return card && Data.user.teamCard.findIndex(iCard => iCard && iCard.card.sid == card.card.sid) >= 0 } equipIsUp(equip: IEquip): boolean { return equip.equip.hero != '' } checkRoleLevelUpNeed(iRole: IRole): IOperateNeed { let roleLevelConfig: IRoleLevelConfig = RoleLevelConfig[iRole.hero.lv + 1] let idNumArr: idNum[] = roleLevelConfig ? this.getIdNumArr(roleLevelConfig.goods, roleLevelConfig.goodNum) : [] let operateNeed = this.getOperateNeed(idNumArr) operateNeed.isMax = iRole.hero.lv >= RoleQualityConfig[iRole.cfg.quality].maxLv || iRole.hero.lv >= Data.user.level operateNeed.canUp &&= !operateNeed.isMax return operateNeed } getNoSelfRoleNum(iRoles: IRole[], selfRole: IRole) { if (!iRoles) return 0 return iRoles.filter(value => value.hero.sid != selfRole.hero.sid).length } checkRoleBreakNeed(role: IRole, isAuto: boolean = false): IOperateNeed { let canBreak = true let breakCfg = RoleQualityConfig[role.cfg.quality + 1] let need: needIdNum[] = [] let needNum = 0 let hasNum = 0 if (breakCfg) { if (breakCfg.anyQuality > 0) { //消耗某一品质 let roleNum = this.getNoSelfRoleNum(this.qualityRoleMap.get(breakCfg.anyQuality), role) hasNum = roleNum + Mgr.goods.getGoodsNum(breakCfg.resetGoods) needNum = breakCfg.anyQualityNum - hasNum need.push({id: breakCfg.resetGoods, num: hasNum, need: needNum}) } else if (breakCfg.sameQualityNum > 0) { //消耗同名同品质卡 hasNum = this.getNoSelfRoleNum(this.sameIDRoleMap.get(role.hero.id), role) //一键合成 if (isAuto) { let iRoles = this.sameIDRoleMap.get(role.hero.id) if (iRoles) { hasNum = iRoles.filter( tmp => tmp.hero.sid != role.hero.sid && tmp.equips.findIndex(v => v != null) < 0 && tmp.hero.lv == 1, ).length } } needNum = breakCfg.sameQualityNum - hasNum need.push({id: role.hero.id, num: hasNum, need: needNum}) } canBreak &&= needNum < 0 } canBreak &&= !role.isAlter let isMax = role.cfg.quality >= Data.main.maxRoleQuality return {need, canUp: canBreak && !isMax, isMax} } checkCardLevelUpNeed(iCard: ICard): IOperateNeed { let cardLevelConfig: ICardLevelConfig = CardLevelConfig[iCard.card.lv + 1] let idNumArr: idNum[] = cardLevelConfig ? this.getIdNumArr(cardLevelConfig.goods, cardLevelConfig.goodNum) : [] let operateNeed = this.getOperateNeed(idNumArr) operateNeed.isMax = iCard.card.lv >= RoleQualityConfig[iCard.cfg.quality].maxLv || iCard.card.lv >= Data.user.level operateNeed.canUp &&= !operateNeed.isMax return operateNeed } checkCardBreakNeed(iCard: ICard): IOperateNeed { let idNumArr: needIdNum[] = [] let cardDebris: ICardDebris = Data.user.cardDebris.find( cardDebris => cardDebris.cfg.card === iCard.cfg.ID - iCard.cfg.quality + 1, ) let hasNum = cardDebris ? cardDebris.num : 0 let nextCfg = CardSkillConfig[iCard.cfg.ID + 1] idNumArr.push({id: iCard.debrisCfg.ID, num: hasNum, need: (nextCfg ? nextCfg.consume : 0) - hasNum}) let isMax = iCard.cfg.quality >= Data.main.maxCardQuality let canUp = !isMax && idNumArr[0].need <= 0 return {need: idNumArr, canUp, isMax} } checkBuildLevelUpNeed(build: building) { let nextCfg = BuildingConfig[build.id * 10000 + build.level + 1] let idNumArr: idNum[] = nextCfg ? this.getIdNumArr(nextCfg.goods, nextCfg.goodsNum) : [] let operateNeed = this.getOperateNeed(idNumArr) operateNeed.isMax = nextCfg == undefined operateNeed.canUp &&= !operateNeed.isMax return operateNeed } checkCastleSkillLvNeed(skill: ICastleSkill) { let nextCfg = CastleSkillConfig[skill.cfg.ID + 1] let idNumArr: idNum[] = nextCfg ? this.getIdNumByCfgArr(nextCfg.upgrade) : [] let operateNeed = this.getOperateNeed(idNumArr) operateNeed.isMax = nextCfg == undefined operateNeed.canUp &&= !operateNeed.isMax return operateNeed } checkCardDebrisMerge(cardDebris: ICardDebris): IOperateNeed { let needArr: needIdNum[] = [ { id: cardDebris.cfg.ID, num: cardDebris.num, need: cardDebris.cfg.num - cardDebris.num, }, ] let operateNeed: IOperateNeed = { need: needArr, canUp: needArr[0].need <= 0 && !Data.user.cards.find( value => Math.floor(value.card.id / 100) == Math.floor(cardDebris.cfg.card / 100), ), isMax: false, } return operateNeed } getNoSelfEquipNum(equips: IEquip[], selfEquip: IEquip) { if (!equips) return 0 return equips.filter(value => value.equip.sid != selfEquip.equip.sid).length } checkEquipBreakNeed(equip: IEquip, isAuto: boolean = false): IOperateNeed { let canBreak = false let breakCfg = EquipmentQualityConfig[equip.cfg.quality + 1] let need: needIdNum[] = [] let needNum = 0 let hasNum = 0 if (breakCfg) { if (breakCfg.anyQuality > 0) { //消耗某一品质 let num = this.getNoSelfEquipNum( this.qualityEquipMap.get(breakCfg.anyQuality)?.filter(value => value.cfg.type == equip.cfg.type), equip, ) hasNum = num + Mgr.goods.getGoodsNum(breakCfg.resetGoods[equip.cfg.type - 1]) needNum = breakCfg.anyQualityNum - hasNum canBreak ||= needNum < 0 need.push({id: breakCfg.resetGoods[equip.cfg.type - 1], num: hasNum, need: needNum}) } else if (breakCfg.sameQualityNum > 0) { //消耗同名同品质装备 hasNum = this.getNoSelfEquipNum(this.sameIDEquipMap.get(equip.equip.id), equip) //一键合成 if (isAuto) { let filterArr = this.sameIDEquipMap.get(equip.equip.id) hasNum = filterArr ? filterArr.filter(tmp => tmp.equip.sid != equip.equip.sid && tmp.equip.lv == 1).length : 0 } needNum = breakCfg.sameQualityNum - hasNum canBreak ||= needNum < 0 need.push({id: equip.equip.id, num: hasNum, need: needNum}) } } let isMax = equip.cfg.quality >= Data.main.maxRoleQuality return {need, canUp: canBreak && !isMax, isMax} } checkEquipLevelNeed(equip: IEquip): IOperateNeed { let cfg: IEquipmentLevelConfig = EquipmentLevelConfig[equip.equip.lv + 1] let idNumArr: idNum[] = [] if (cfg) { idNumArr.push({id: GOODS.coin, num: cfg.goodNum}) idNumArr.push({id: GOODS.weaponsScroll + equip.cfg.type - 1, num: cfg.scrollNum}) } let operateNeed = this.getOperateNeed(idNumArr) operateNeed.isMax = equip.equip.lv >= EquipmentQualityConfig[equip.cfg.quality]?.maxLv || equip.equip.lv >= Data.user.level operateNeed.canUp &&= !operateNeed.isMax return operateNeed } checkEquipWearUp(role: IRole, equip: IEquip): boolean { let wearEquip = role.equips.find(v => v && v.cfg.type == equip.cfg.type) return ( equip.cfg.profession.includes(role.cfg.profession) && (wearEquip ? equip.cfg.quality > wearEquip.cfg.quality : true) ) } checkRoleWearEquipUp(role: IRole): boolean { if (!this.roleIsUp(role)) return false for (let i = 0; i < role.equips.length; i++) { let findIndex = Data.user.equips.findIndex( v => !v.equip.hero && v.cfg.type == i + 1 && (!role.equips[i] || v.cfg.quality > role.equips[i].cfg.quality) && v.cfg.profession.includes(role.cfg.profession), ) if (findIndex >= 0) { return true } } return false } checkRoleEquipUp(role: IRole): boolean { if (!this.roleIsUp(role)) return false return role.equips.some( equip => equip && (this.checkEquipLevelNeed(equip).canUp || this.checkEquipBreakNeed(equip).canUp), ) } //检查祭坛是否有空位 且英雄祭坛是否有英雄可以上阵 checkAltarIsSeat(): boolean { let isAlter = false //是否在祭坛中是否有空位 let isHero = false //自己的英雄背包中是否有可上阵的英雄 Data.user.altarInfoList.forEach((value, key) => { if (!value.sid) { isAlter = true } }) for (let i = 0; i < Data.user.roles.length; i++) { let value = Data.user.roles[i] if ( //1、品质必须是紫色品质以上 2、不在祭坛中上阵、 3、不在祭坛中展示(祭坛前五) value.cfg.qualityType >= QUALITY_TYPE.elite && !value.isAlter && Data.user.altarTopFive.indexOf(value.hero.sid) == -1 ) { isHero = true } //如果祭坛中有空位、 且有英雄中有可以上阵就直接返回数据 不需要继续循环了 if (isAlter && isHero) return isAlter && isHero } return isAlter && isHero } getNextCanActiveTalents(): ITalentConfig[] { let allTalents = Object.values(TalentConfig) let smallTalents = allTalents.filter(v => v.talentType == 1) let bigTalents = allTalents.filter(v => v.talentType == 2) let curSmallUpIndex = -1 let curBigUpIndex = -1 for (let i = Data.user.talents.length - 1; i >= 0; i--) { let cfg = TalentConfig[Data.user.talents[i]] if (cfg && cfg.talentType == 1 && curSmallUpIndex < 0) { curSmallUpIndex = smallTalents.findIndex(v => v.ID == cfg.ID) } else if (cfg && cfg.talentType == 2 && curBigUpIndex < 0) { curBigUpIndex = bigTalents.findIndex(v => v.ID == cfg.ID) } } return [smallTalents[curSmallUpIndex + 1], bigTalents[curBigUpIndex + 1]] } checkTalentUp() { let cfgArr = this.getNextCanActiveTalents() return ( (cfgArr[0] && this.getOperateNeed(this.getLongIdNumByCfgArr(cfgArr[0].goods)).canUp && cfgArr[0].lv <= Data.user.level) || (cfgArr[1] && this.getOperateNeed(this.getLongIdNumByCfgArr(cfgArr[1].goods)).canUp && cfgArr[1].lv <= Data.user.level) ) } getRewardsNty(cmd: string) { let rewards = Data.main.rewardNtyMap.get(cmd) Data.main.rewardNtyMap.delete(cmd) return rewards } flyGoods(goodsID: number, startPos: cc.Vec3, finishCb?: Function) { let cbArr = this.flyGoodsCBMap.get(goodsID) if (!cbArr) { cbArr = [] this.flyGoodsCBMap.set(goodsID, cbArr) } cbArr.push(finishCb) let endPos = this.goodsEndPosMap?.get(goodsID) //if (!endPos) endPos = this.bagEndPos if (!endPos) return if (!this.pools) this.pools = new Map() if (!this.pools.get(goodsID)) { this.pools.set(goodsID, new cc.NodePool()) } let cfg = GoodsConfig[goodsID] Data.main.texBundle.load(`Public/goods/${cfg.icon}`, cc.SpriteFrame, (error, res: cc.SpriteFrame) => { if (error) { console.error(error) return } //道具缓存,不释放 if (res.refCount < 100) res.addRef() let nodes = [] for (let i = 0; i < 10; i++) { let goods = this.pools.get(goodsID).get() if (!goods) { goods = cc.instantiate(new cc.Node()) goods.addComponent(cc.Sprite) } goods.getComponent(cc.Sprite).spriteFrame = res nodes.push(goods) } ccUtils.circleFlyNodes( nodes, cc.Canvas.instance.node, startPos, endPos, node => { this.pools.get(goodsID).put(node) }, () => { let fuc = cbArr.shift() fuc && fuc() }, ) }) } checkBorn(id: number): number[] { let goodConfig = GoodsConfig[id], cardConfig = CardConsumeConfig[id], born: number[] = [] if (goodConfig) { born = goodConfig.born } if (cardConfig) { born = cardConfig.born } return born } }