GoodsManager.ts 28 KB

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