GoodsManager.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /** @format */
  2. import {ccUtils} from '../utils/ccUtils'
  3. import {Data, Mgr} from '../GameControl'
  4. import {building, idNum} from '../proto/typedef'
  5. import {GoodsConfig} from '../config/GoodsConfig'
  6. import {BaseUI} from '../ui/BaseUI'
  7. import {IRoleLevelConfig, RoleLevelConfig} from '../config/RoleLevelConfig'
  8. import {CardLevelConfig, ICardLevelConfig} from '../config/CardLevelConfig'
  9. import {RoleQualityConfig} from '../config/RoleQualityConfig'
  10. import {CardSkillConfig} from '../config/CardSkillConfig'
  11. import {GOODS, PREFAB_TYPE, QUALITY_TYPE} from '../enums/Enum'
  12. import {EquipmentQualityConfig} from '../config/EquipmentQualityConfig'
  13. import {EquipmentLevelConfig, IEquipmentLevelConfig} from '../config/EquipmentLevelConfig'
  14. import {RoleConfig} from '../config/RoleConfig'
  15. import {ArmorConfig} from '../config/ArmorConfig'
  16. import {CardConsumeConfig} from '../config/CardConsumeConfig'
  17. import {
  18. ICard,
  19. ICardDebris,
  20. ICastleSkill,
  21. IEquip,
  22. IGoodShowInfo,
  23. IOperateNeed,
  24. IRole,
  25. needIdNum,
  26. } from '../interface/GlobalInterface'
  27. import {UI} from '../enums/UI'
  28. import {IRewardNty, ItemUICfg} from '../interface/UIInterface'
  29. import {ITalentConfig, TalentConfig} from '../config/TalentConfig'
  30. import FrameAnimation from '../uiutils/FrameAnimation'
  31. import {CastleSkillConfig} from '../config/CastleSkillConfig'
  32. export class GoodsManager {
  33. pools: Map<number, cc.NodePool>
  34. goodsEndPosMap: Map<number, cc.Vec3> = new Map()
  35. bagEndPos: cc.Vec3
  36. qualityRoleMap: Map<number, IRole[]> = new Map<number, IRole[]>()
  37. sameIDRoleMap: Map<number, IRole[]> = new Map<number, IRole[]>()
  38. qualityEquipMap: Map<number, IEquip[]> = new Map<number, IEquip[]>()
  39. sameIDEquipMap: Map<number, IEquip[]> = new Map<number, IEquip[]>()
  40. startPoint: cc.Vec2 //开始触摸的位置
  41. curPoint: cc.Vec2 //触摸的当前位置
  42. moveOverstepPx: number = 30 //触摸物品后移动超过多少像素就不弹出详细信息
  43. flyGoodsCBMap: Map<number, Function[]> = new Map()
  44. reset() {
  45. this.pools = new Map()
  46. this.goodsEndPosMap.clear()
  47. this.qualityRoleMap.clear()
  48. this.sameIDRoleMap.clear()
  49. this.qualityEquipMap.clear()
  50. this.sameIDEquipMap.clear()
  51. this.flyGoodsCBMap.clear()
  52. }
  53. getGoodsNum(ID: number) {
  54. let num = Data.user.goods.get(ID)
  55. return num ? num : 0
  56. }
  57. setGoodsNum(ID: number, num: number) {
  58. Data.user.goods.set(ID, num)
  59. }
  60. initGoods(goods: idNum[], nodes: cc.Node[], baseUI: BaseUI) {
  61. if (goods.length != nodes.length) cc.error('initGoods失败,goods数量和nodes数量不一致')
  62. for (let i = 0; i < goods.length; i++) {
  63. let parent = nodes[i]
  64. if (goods[i] && parent) this.initOneGoods(goods[i], parent, baseUI)
  65. }
  66. }
  67. detailsTouchStart(flag, event) {
  68. this.startPoint = event.getLocation()
  69. this.curPoint = event.getLocation() //如果不移动的话当前位置会是空、所以默认给开始位置
  70. }
  71. detailsTouchMove(flag, event) {
  72. this.curPoint = event.getLocation()
  73. }
  74. initOneGoods(goods: idNum, parent: cc.Node, baseUI: BaseUI, itemUICfg: ItemUICfg = {showDetails: true}) {
  75. let {quality, iconUrl, grade, stacking, isDebris} = this.getGoodShowInfo(goods.id)
  76. let node = Mgr.global.getItemNode(parent, PREFAB_TYPE.goods, `${goods.id}_${quality}`, baseUI)
  77. if (itemUICfg && itemUICfg.changeQuality) {
  78. quality = itemUICfg.changeQuality
  79. }
  80. node.targetOff(this)
  81. if (itemUICfg && itemUICfg.showDetails) {
  82. node.on(cc.Node.EventType.TOUCH_START, this.detailsTouchStart.bind(this, true), this)
  83. node.on(cc.Node.EventType.TOUCH_END, this.showGoodsDetails.bind(this, goods.id), this)
  84. node.on(cc.Node.EventType.TOUCH_MOVE, this.detailsTouchMove.bind(this, false), this)
  85. }
  86. ccUtils.setLabel(`${stacking ? Math.toKMBNum(goods.num) : ''}`, node, 'lb')
  87. cc.find('lb', node).active = goods.num > 0
  88. baseUI.loadNotRefTexImg(`Public/goodsQuality/item_frame${quality}`, node, 'bg')
  89. baseUI.loadNotRefTexImg(iconUrl, node, 'icon')
  90. let gradeNode = cc.find('grade', node)
  91. if (gradeNode) {
  92. gradeNode.active = grade > 0
  93. if (grade > 0) {
  94. baseUI.loadNotRefTexImg(`Public/role/grade_${quality}`, node, 'grade')
  95. ccUtils.setLabel(grade.toString(), node, 'grade/lv')
  96. }
  97. }
  98. let debris = cc.find('debris', node)
  99. if (debris) {
  100. debris.active = isDebris
  101. }
  102. }
  103. showGoodsDetails(goodID: number) {
  104. let isXOverstep = Math.abs(this.curPoint.x - this.startPoint.x) <= this.moveOverstepPx
  105. let isYOverstep = Math.abs(this.curPoint.y - this.startPoint.y) <= this.moveOverstepPx
  106. if (isXOverstep && isYOverstep) {
  107. Mgr.ui.show(UI.ItemDetailsUI, this.getGoodShowInfo(goodID))
  108. }
  109. }
  110. async showRectAni(item, showQuality: number, baseUI: BaseUI) {
  111. let rectAni = cc.find('rectAni', item)
  112. if (!rectAni) return
  113. let quality = 'light'
  114. let show = true
  115. if (showQuality > 1 && showQuality < 100) {
  116. quality = showQuality.toString()
  117. } else if (showQuality > 100) {
  118. let showInfo = this.getGoodShowInfo(showQuality)
  119. quality = showInfo.quality.toString()
  120. show = [PREFAB_TYPE.card, PREFAB_TYPE.equip, PREFAB_TYPE.role].includes(showInfo.goodType)
  121. }
  122. let sa = await Mgr.res.loadTexSync(`Public/goodsQuality/rectAni/goods_rect_ani_${quality}`)
  123. let frameAnimation = rectAni.getComponent(FrameAnimation)
  124. if (sa && cc.isValid(rectAni) && show) {
  125. rectAni.active = true
  126. frameAnimation.init(sa, Infinity, true)
  127. frameAnimation.play(0, true)
  128. } else {
  129. rectAni.active = false
  130. }
  131. }
  132. initNeedGoods(goods: needIdNum[], nodes: cc.Node[], baseUI: BaseUI) {
  133. for (let i = 0; i < nodes.length; i++) {
  134. let item = nodes[i]
  135. let cfg = GoodsConfig[goods[i].id]
  136. baseUI.loadNotRefTexImg(`Public/goods/${cfg.icon}`, item, 'icon')
  137. let hasNode = cc.find('has', item)
  138. ccUtils.setLabel(Math.toKMBNum(Mgr.goods.getGoodsNum(goods[i].id)), hasNode)
  139. ccUtils.setLabel(`/${Math.toKMBNum(goods[i].num)}`, item, 'need')
  140. let can = goods[i].need <= 0
  141. hasNode.color = cc.Color.GREEN.fromHEX(can ? '#BAFF27' : '#FF2525')
  142. }
  143. }
  144. getIdNumArr(goods: number[], goodsNum: number[]) {
  145. let arr: idNum[] = []
  146. for (let i = 0; i < goods.length; i++) {
  147. arr.push({id: goods[i], num: goodsNum[i]})
  148. }
  149. return arr
  150. }
  151. getIdNumByCfgArr(goods: number[][]) {
  152. let arr: idNum[] = []
  153. for (let i = 0; i < goods.length; i++) {
  154. arr.push({id: goods[i][0], num: goods[i][1]})
  155. }
  156. return arr
  157. }
  158. /** 长数组转为idNum类型
  159. * 传值结构:[11503, 1, 130001, 60, 110001, 10]
  160. * 返回结构:[{id:11503,num:1},{id:130001,num:60},{id:110001,num:10}]
  161. */
  162. getLongIdNumByCfgArr(goods: number[]) {
  163. let arr: idNum[] = []
  164. for (let i = 0; i < goods.length - 1; i += 2) {
  165. arr.push({id: goods[i], num: goods[i + 1]})
  166. }
  167. return arr
  168. }
  169. getGoodsListByRewardNty(rewardNty: IRewardNty) {
  170. let idNumArr = [].concat(rewardNty.changeArr)
  171. for (let iCard of rewardNty.iCards) {
  172. idNumArr.push({
  173. id: iCard.cfg.ID,
  174. num: 1,
  175. })
  176. }
  177. for (let iRole of rewardNty.iRoles) {
  178. idNumArr.push({
  179. id: iRole.cfg.ID,
  180. num: 1,
  181. })
  182. }
  183. for (let iEquip of rewardNty.iEquips) {
  184. idNumArr.push({
  185. id: iEquip.cfg.ID,
  186. num: 1,
  187. })
  188. }
  189. for (let debris of rewardNty.debrisArr) {
  190. idNumArr.push({
  191. id: debris.id,
  192. num: debris.num,
  193. })
  194. }
  195. return this.getGoodsList(idNumArr)
  196. }
  197. getGoodsList(arr: idNum[]) {
  198. let newArr: idNum[] = []
  199. for (let i = 0; i < arr.length; i++) {
  200. let idNum = arr[i]
  201. let index = newArr.findIndex(
  202. v => this.getGoodShowInfo(v.id).quality < this.getGoodShowInfo(idNum.id).quality,
  203. )
  204. let hasIndex = newArr.findIndex(v => v.id == idNum.id)
  205. if (hasIndex == -1 && index == -1) index = newArr.length
  206. if (this.getGoodShowInfo(idNum.id).stacking) {
  207. if (hasIndex != -1) {
  208. newArr[hasIndex].num += idNum.num
  209. } else {
  210. newArr.splice(index, 0, idNum)
  211. }
  212. } else {
  213. newArr.splice(hasIndex >= 0 ? hasIndex : index, 0, ...Array(idNum.num).fill({id: idNum.id, num: 1}))
  214. }
  215. }
  216. return newArr
  217. }
  218. getGoodShowInfo(id: number): IGoodShowInfo {
  219. let quality: number
  220. let iconUrl = ''
  221. let name = ''
  222. let grade: number = 0
  223. let stacking = false
  224. let isDebris = false
  225. let goodType: PREFAB_TYPE = null
  226. let goodsCfg = GoodsConfig[id]
  227. let roleCfg = RoleConfig[id]
  228. let cardSkillCfg = CardSkillConfig[id]
  229. let cardConsumeCfg = CardConsumeConfig[id]
  230. let armorConfig = ArmorConfig[id]
  231. if (goodsCfg) {
  232. quality = goodsCfg.quality
  233. iconUrl = `Public/goods/${goodsCfg.icon}`
  234. stacking = goodsCfg.stacking == 0
  235. name = goodsCfg.name
  236. goodType = PREFAB_TYPE.goods
  237. }
  238. if (roleCfg) {
  239. quality = roleCfg.qualityType
  240. iconUrl = `Public/role/icon/${roleCfg.url}`
  241. grade = Data.user.gradeArr[roleCfg.quality - 1]
  242. name = roleCfg.name
  243. goodType = PREFAB_TYPE.role
  244. }
  245. if (cardSkillCfg) {
  246. quality = cardSkillCfg.qualityType
  247. iconUrl = `Public/card/icon/${cardSkillCfg.url}`
  248. grade = Data.user.gradeArr[cardSkillCfg.quality - 1]
  249. name = cardSkillCfg.name
  250. goodType = PREFAB_TYPE.card
  251. }
  252. if (cardConsumeCfg) {
  253. quality = cardConsumeCfg.qualityType
  254. iconUrl = `Public/card/icon/${cardConsumeCfg.url}`
  255. isDebris = true
  256. stacking = true
  257. name = cardConsumeCfg.name
  258. goodType = PREFAB_TYPE.cardDebris
  259. }
  260. if (armorConfig) {
  261. iconUrl = `Public/equip/icon/${armorConfig.icon}`
  262. quality = armorConfig.qualityType
  263. grade = Data.user.gradeArr[armorConfig.quality - 1]
  264. name = armorConfig.name
  265. goodType = PREFAB_TYPE.equip
  266. }
  267. return {quality, iconUrl, grade, stacking, isDebris, name, goodType, id}
  268. }
  269. getOperateNeed(idNums: idNum[]): IOperateNeed {
  270. let needArr: needIdNum[] = []
  271. let hasGoods = true
  272. for (let goods of idNums) {
  273. let data = {id: goods.id, num: goods.num, need: goods.num - this.getGoodsNum(goods.id)}
  274. needArr.push(data)
  275. hasGoods &&= data.need <= 0
  276. }
  277. return {need: needArr, canUp: hasGoods, isMax: false}
  278. }
  279. reactRolesChange() {
  280. this.qualityRoleMap.forEach((value, key) => {
  281. value.length = 0
  282. })
  283. this.sameIDRoleMap.forEach((value, key) => {
  284. value.length = 0
  285. })
  286. Data.user.roles.forEach(iRole => {
  287. let quality = iRole.cfg.quality
  288. if (this.roleIsUp(iRole)) return
  289. let list = this.qualityRoleMap.get(quality)
  290. let idList = this.sameIDRoleMap.get(iRole.hero.id)
  291. if (!list) {
  292. list = []
  293. this.qualityRoleMap.set(quality, list)
  294. }
  295. list.push(iRole)
  296. if (!idList) {
  297. idList = []
  298. this.sameIDRoleMap.set(iRole.hero.id, idList)
  299. }
  300. idList.push(iRole)
  301. })
  302. this.sortRole()
  303. Data.user.rolesDirty = !Data.user.rolesDirty
  304. }
  305. reactCardsChange() {
  306. this.sortCard()
  307. Data.user.cardsDirty = !Data.user.cardsDirty
  308. }
  309. reactEquipsChange() {
  310. this.qualityEquipMap.forEach((value, key) => {
  311. value.length = 0
  312. })
  313. this.sameIDEquipMap.forEach((value, key) => {
  314. value.length = 0
  315. })
  316. Data.user.equips.forEach(iEquip => {
  317. let quality = iEquip.cfg.quality
  318. if (this.equipIsUp(iEquip)) return
  319. let list = this.qualityEquipMap.get(quality)
  320. let idList = this.sameIDEquipMap.get(iEquip.equip.id)
  321. if (!list) {
  322. list = []
  323. this.qualityEquipMap.set(quality, list)
  324. }
  325. list.push(iEquip)
  326. if (!idList) {
  327. idList = []
  328. this.sameIDEquipMap.set(iEquip.equip.id, idList)
  329. }
  330. idList.push(iEquip)
  331. })
  332. this.sortEquip()
  333. Data.user.equipsDirty = !Data.user.equipsDirty
  334. }
  335. baseSortRule(a, b, aIndex, bIndex) {
  336. if (aIndex != bIndex) {
  337. if (aIndex >= 0 && bIndex >= 0) {
  338. //return aIndex - bIndex
  339. return b.power - a.power
  340. } else {
  341. return bIndex - aIndex
  342. }
  343. }
  344. if (a.cfg.quality != b.cfg.quality) {
  345. return b.cfg.quality - a.cfg.quality
  346. }
  347. return b.power - a.power
  348. }
  349. sortRole() {
  350. Data.user.roles.sort((a, b) => {
  351. let aIndex = Data.user.teamRole.indexOf(a)
  352. let bIndex = Data.user.teamRole.indexOf(b)
  353. return this.baseSortRule(a, b, aIndex, bIndex)
  354. })
  355. }
  356. sortCard() {
  357. Data.user.cards.sort((a, b) => {
  358. let aIndex = Data.user.teamCard.indexOf(a)
  359. let bIndex = Data.user.teamCard.indexOf(b)
  360. return this.baseSortRule(a, b, aIndex, bIndex)
  361. })
  362. }
  363. sortCardDebris(debris: ICardDebris[]) {
  364. debris.sort((a, b) => {
  365. return b.num - a.num
  366. })
  367. }
  368. sortEquip() {
  369. Data.user.equips.sort((a, b) => {
  370. if (a.cfg.quality != b.cfg.quality) {
  371. return b.cfg.quality - a.cfg.quality
  372. }
  373. if (a.equip.lv != b.equip.lv) {
  374. return b.equip.lv - a.equip.lv
  375. }
  376. if (a.cfg.type != b.cfg.type) {
  377. return a.cfg.type - b.cfg.type
  378. }
  379. })
  380. }
  381. roleIsUp(role: IRole): boolean {
  382. return role && Data.user.teamRole.findIndex(iRole => iRole && iRole.hero.sid == role.hero.sid) >= 0
  383. }
  384. cardIsUp(card: ICard): boolean {
  385. return card && Data.user.teamCard.findIndex(iCard => iCard && iCard.card.sid == card.card.sid) >= 0
  386. }
  387. equipIsUp(equip: IEquip): boolean {
  388. return equip.equip.hero != ''
  389. }
  390. checkRoleLevelUpNeed(iRole: IRole): IOperateNeed {
  391. let roleLevelConfig: IRoleLevelConfig = RoleLevelConfig[iRole.hero.lv + 1]
  392. let idNumArr: idNum[] = roleLevelConfig ? this.getIdNumArr(roleLevelConfig.goods, roleLevelConfig.goodNum) : []
  393. let operateNeed = this.getOperateNeed(idNumArr)
  394. operateNeed.isMax =
  395. iRole.hero.lv >= RoleQualityConfig[iRole.cfg.quality].maxLv || iRole.hero.lv >= Data.user.level
  396. operateNeed.canUp &&= !operateNeed.isMax
  397. return operateNeed
  398. }
  399. getNoSelfRoleNum(iRoles: IRole[], selfRole: IRole) {
  400. if (!iRoles) return 0
  401. return iRoles.filter(value => value.hero.sid != selfRole.hero.sid).length
  402. }
  403. checkRoleBreakNeed(role: IRole, isAuto: boolean = false): IOperateNeed {
  404. let canBreak = true
  405. let breakCfg = RoleQualityConfig[role.cfg.quality + 1]
  406. let need: needIdNum[] = []
  407. let needNum = 0
  408. let hasNum = 0
  409. if (breakCfg) {
  410. if (breakCfg.anyQuality > 0) {
  411. //消耗某一品质
  412. let roleNum = this.getNoSelfRoleNum(this.qualityRoleMap.get(breakCfg.anyQuality), role)
  413. hasNum = roleNum + Mgr.goods.getGoodsNum(breakCfg.resetGoods)
  414. needNum = breakCfg.anyQualityNum - hasNum
  415. need.push({id: breakCfg.resetGoods, num: hasNum, need: needNum})
  416. } else if (breakCfg.sameQualityNum > 0) {
  417. //消耗同名同品质卡
  418. hasNum = this.getNoSelfRoleNum(this.sameIDRoleMap.get(role.hero.id), role)
  419. //一键合成
  420. if (isAuto) {
  421. let iRoles = this.sameIDRoleMap.get(role.hero.id)
  422. if (iRoles) {
  423. hasNum = iRoles.filter(
  424. tmp =>
  425. tmp.hero.sid != role.hero.sid &&
  426. tmp.equips.findIndex(v => v != null) < 0 &&
  427. tmp.hero.lv == 1,
  428. ).length
  429. }
  430. }
  431. needNum = breakCfg.sameQualityNum - hasNum
  432. need.push({id: role.hero.id, num: hasNum, need: needNum})
  433. }
  434. canBreak &&= needNum < 0
  435. }
  436. canBreak &&= !role.isAlter
  437. let isMax = role.cfg.quality >= Data.main.maxRoleQuality
  438. return {need, canUp: canBreak && !isMax, isMax}
  439. }
  440. checkCardLevelUpNeed(iCard: ICard): IOperateNeed {
  441. let cardLevelConfig: ICardLevelConfig = CardLevelConfig[iCard.card.lv + 1]
  442. let idNumArr: idNum[] = cardLevelConfig ? this.getIdNumArr(cardLevelConfig.goods, cardLevelConfig.goodNum) : []
  443. let operateNeed = this.getOperateNeed(idNumArr)
  444. operateNeed.isMax =
  445. iCard.card.lv >= RoleQualityConfig[iCard.cfg.quality].maxLv || iCard.card.lv >= Data.user.level
  446. operateNeed.canUp &&= !operateNeed.isMax
  447. return operateNeed
  448. }
  449. checkCardBreakNeed(iCard: ICard): IOperateNeed {
  450. let idNumArr: needIdNum[] = []
  451. let cardDebris: ICardDebris = Data.user.cardDebris.find(
  452. cardDebris => cardDebris.cfg.card === iCard.cfg.ID - iCard.cfg.quality + 1,
  453. )
  454. let hasNum = cardDebris ? cardDebris.num : 0
  455. let nextCfg = CardSkillConfig[iCard.cfg.ID + 1]
  456. idNumArr.push({id: iCard.debrisCfg.ID, num: hasNum, need: (nextCfg ? nextCfg.consume : 0) - hasNum})
  457. let isMax = iCard.cfg.quality >= Data.main.maxCardQuality
  458. let canUp = !isMax && idNumArr[0].need <= 0
  459. return {need: idNumArr, canUp, isMax}
  460. }
  461. checkCastleSkillLvNeed(skill: ICastleSkill) {
  462. let nextCfg = CastleSkillConfig[skill.cfg.ID + 1]
  463. let idNumArr: idNum[] = nextCfg ? this.getIdNumByCfgArr(nextCfg.upgrade) : []
  464. let operateNeed = this.getOperateNeed(idNumArr)
  465. operateNeed.isMax = nextCfg == undefined
  466. operateNeed.canUp &&= !operateNeed.isMax
  467. return operateNeed
  468. }
  469. checkCardDebrisMerge(cardDebris: ICardDebris): IOperateNeed {
  470. let needArr: needIdNum[] = [
  471. {
  472. id: cardDebris.cfg.ID,
  473. num: cardDebris.num,
  474. need: cardDebris.cfg.num - cardDebris.num,
  475. },
  476. ]
  477. let operateNeed: IOperateNeed = {
  478. need: needArr,
  479. canUp:
  480. needArr[0].need <= 0 &&
  481. !Data.user.cards.find(
  482. value => Math.floor(value.card.id / 100) == Math.floor(cardDebris.cfg.card / 100),
  483. ),
  484. isMax: false,
  485. }
  486. return operateNeed
  487. }
  488. getNoSelfEquipNum(equips: IEquip[], selfEquip: IEquip) {
  489. if (!equips) return 0
  490. return equips.filter(value => value.equip.sid != selfEquip.equip.sid).length
  491. }
  492. checkEquipBreakNeed(equip: IEquip, isAuto: boolean = false): IOperateNeed {
  493. let canBreak = false
  494. let breakCfg = EquipmentQualityConfig[equip.cfg.quality + 1]
  495. let need: needIdNum[] = []
  496. let needNum = 0
  497. let hasNum = 0
  498. if (breakCfg) {
  499. if (breakCfg.anyQuality > 0) {
  500. //消耗某一品质
  501. let num = this.getNoSelfEquipNum(
  502. this.qualityEquipMap.get(breakCfg.anyQuality)?.filter(value => value.cfg.type == equip.cfg.type),
  503. equip,
  504. )
  505. hasNum = num + Mgr.goods.getGoodsNum(breakCfg.resetGoods[equip.cfg.type - 1])
  506. needNum = breakCfg.anyQualityNum - hasNum
  507. canBreak ||= needNum < 0
  508. need.push({id: breakCfg.resetGoods[equip.cfg.type - 1], num: hasNum, need: needNum})
  509. } else if (breakCfg.sameQualityNum > 0) {
  510. //消耗同名同品质装备
  511. hasNum = this.getNoSelfEquipNum(this.sameIDEquipMap.get(equip.equip.id), equip)
  512. //一键合成
  513. if (isAuto) {
  514. let filterArr = this.sameIDEquipMap.get(equip.equip.id)
  515. hasNum = filterArr
  516. ? filterArr.filter(tmp => tmp.equip.sid != equip.equip.sid && tmp.equip.lv == 1).length
  517. : 0
  518. }
  519. needNum = breakCfg.sameQualityNum - hasNum
  520. canBreak ||= needNum < 0
  521. need.push({id: equip.equip.id, num: hasNum, need: needNum})
  522. }
  523. }
  524. let isMax = equip.cfg.quality >= Data.main.maxRoleQuality
  525. return {need, canUp: canBreak && !isMax, isMax}
  526. }
  527. checkEquipLevelNeed(equip: IEquip): IOperateNeed {
  528. let cfg: IEquipmentLevelConfig = EquipmentLevelConfig[equip.equip.lv + 1]
  529. let idNumArr: idNum[] = []
  530. if (cfg) {
  531. idNumArr.push({id: GOODS.coin, num: cfg.goodNum})
  532. idNumArr.push({id: GOODS.weaponsScroll + equip.cfg.type - 1, num: cfg.scrollNum})
  533. }
  534. let operateNeed = this.getOperateNeed(idNumArr)
  535. operateNeed.isMax =
  536. equip.equip.lv >= EquipmentQualityConfig[equip.cfg.quality]?.maxLv || equip.equip.lv >= Data.user.level
  537. operateNeed.canUp &&= !operateNeed.isMax
  538. return operateNeed
  539. }
  540. checkEquipWearUp(role: IRole, equip: IEquip): boolean {
  541. let wearEquip = role.equips.find(v => v && v.cfg.type == equip.cfg.type)
  542. return (
  543. equip.cfg.profession.includes(role.cfg.profession) &&
  544. (wearEquip ? equip.cfg.quality > wearEquip.cfg.quality : true)
  545. )
  546. }
  547. checkRoleWearEquipUp(role: IRole): boolean {
  548. if (!this.roleIsUp(role)) return false
  549. for (let i = 0; i < role.equips.length; i++) {
  550. let findIndex = Data.user.equips.findIndex(
  551. v =>
  552. !v.equip.hero &&
  553. v.cfg.type == i + 1 &&
  554. (!role.equips[i] || v.cfg.quality > role.equips[i].cfg.quality) &&
  555. v.cfg.profession.includes(role.cfg.profession),
  556. )
  557. if (findIndex >= 0) {
  558. return true
  559. }
  560. }
  561. return false
  562. }
  563. checkRoleEquipUp(role: IRole): boolean {
  564. if (!this.roleIsUp(role)) return false
  565. return role.equips.some(
  566. equip => equip && (this.checkEquipLevelNeed(equip).canUp || this.checkEquipBreakNeed(equip).canUp),
  567. )
  568. }
  569. //检查祭坛是否有空位 且英雄祭坛是否有英雄可以上阵
  570. checkAltarIsSeat(): boolean {
  571. let isAlter = false //是否在祭坛中是否有空位
  572. let isHero = false //自己的英雄背包中是否有可上阵的英雄
  573. Data.user.altarInfoList.forEach((value, key) => {
  574. if (!value.sid) {
  575. isAlter = true
  576. }
  577. })
  578. for (let i = 0; i < Data.user.roles.length; i++) {
  579. let value = Data.user.roles[i]
  580. if (
  581. //1、品质必须是紫色品质以上 2、不在祭坛中上阵、 3、不在祭坛中展示(祭坛前五)
  582. value.cfg.qualityType >= QUALITY_TYPE.elite &&
  583. !value.isAlter &&
  584. Data.user.altarTopFive.indexOf(value.hero.sid) == -1
  585. ) {
  586. isHero = true
  587. }
  588. //如果祭坛中有空位、 且有英雄中有可以上阵就直接返回数据 不需要继续循环了
  589. if (isAlter && isHero) return isAlter && isHero
  590. }
  591. return isAlter && isHero
  592. }
  593. getNextCanActiveTalents(): ITalentConfig[] {
  594. let allTalents = Object.values(TalentConfig)
  595. let smallTalents = allTalents.filter(v => v.talentType == 1)
  596. let bigTalents = allTalents.filter(v => v.talentType == 2)
  597. let curSmallUpIndex = -1
  598. let curBigUpIndex = -1
  599. for (let i = Data.user.talents.length - 1; i >= 0; i--) {
  600. let cfg = TalentConfig[Data.user.talents[i]]
  601. if (cfg && cfg.talentType == 1 && curSmallUpIndex < 0) {
  602. curSmallUpIndex = smallTalents.findIndex(v => v.ID == cfg.ID)
  603. } else if (cfg && cfg.talentType == 2 && curBigUpIndex < 0) {
  604. curBigUpIndex = bigTalents.findIndex(v => v.ID == cfg.ID)
  605. }
  606. }
  607. return [smallTalents[curSmallUpIndex + 1], bigTalents[curBigUpIndex + 1]]
  608. }
  609. checkTalentUp() {
  610. let cfgArr = this.getNextCanActiveTalents()
  611. return (
  612. (cfgArr[0] &&
  613. this.getOperateNeed(this.getLongIdNumByCfgArr(cfgArr[0].goods)).canUp &&
  614. cfgArr[0].lv <= Data.user.level) ||
  615. (cfgArr[1] &&
  616. this.getOperateNeed(this.getLongIdNumByCfgArr(cfgArr[1].goods)).canUp &&
  617. cfgArr[1].lv <= Data.user.level)
  618. )
  619. }
  620. getRewardsNty(cmd: string) {
  621. let rewards = Data.main.rewardNtyMap.get(cmd)
  622. Data.main.rewardNtyMap.delete(cmd)
  623. return rewards
  624. }
  625. flyGoods(goodsID: number, startPos: cc.Vec3, finishCb?: Function) {
  626. let cbArr = this.flyGoodsCBMap.get(goodsID)
  627. if (!cbArr) {
  628. cbArr = []
  629. this.flyGoodsCBMap.set(goodsID, cbArr)
  630. }
  631. cbArr.push(finishCb)
  632. let endPos = this.goodsEndPosMap?.get(goodsID)
  633. //if (!endPos) endPos = this.bagEndPos
  634. if (!endPos) return
  635. if (!this.pools) this.pools = new Map<number, cc.NodePool>()
  636. if (!this.pools.get(goodsID)) {
  637. this.pools.set(goodsID, new cc.NodePool())
  638. }
  639. let cfg = GoodsConfig[goodsID]
  640. Data.main.texBundle.load(`Public/goods/${cfg.icon}`, cc.SpriteFrame, (error, res: cc.SpriteFrame) => {
  641. if (error) {
  642. console.error(error)
  643. return
  644. }
  645. //道具缓存,不释放
  646. if (res.refCount < 100) res.addRef()
  647. let nodes = []
  648. for (let i = 0; i < 10; i++) {
  649. let goods = this.pools.get(goodsID).get()
  650. if (!goods) {
  651. goods = cc.instantiate(new cc.Node())
  652. goods.addComponent(cc.Sprite)
  653. }
  654. goods.getComponent(cc.Sprite).spriteFrame = res
  655. nodes.push(goods)
  656. }
  657. ccUtils.circleFlyNodes(
  658. nodes,
  659. cc.Canvas.instance.node,
  660. startPos,
  661. endPos,
  662. node => {
  663. this.pools.get(goodsID).put(node)
  664. },
  665. () => {
  666. let fuc = cbArr.shift()
  667. fuc && fuc()
  668. },
  669. )
  670. })
  671. }
  672. checkBorn(id: number): number[] {
  673. let goodConfig = GoodsConfig[id],
  674. cardConfig = CardConsumeConfig[id],
  675. born: number[] = []
  676. if (goodConfig) {
  677. born = goodConfig.born
  678. }
  679. if (cardConfig) {
  680. born = cardConfig.born
  681. }
  682. return born
  683. }
  684. }