GoodsManager.ts 27 KB

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