TalentUI.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /** @format */
  2. import {BaseUI} from './BaseUI'
  3. import {ccUtils} from '../utils/ccUtils'
  4. import {Data, Mgr} from '../GameControl'
  5. import List from '../uiutils/List'
  6. import {RanksLevelConfig} from '../config/RanksLevelConfig'
  7. import {list, node, observer} from '../mobx/observer'
  8. import {ITalentConfig, TalentConfig} from '../config/TalentConfig'
  9. import {DIS_ID, GOODS, LANGUAGE_TYPE} from '../enums/Enum'
  10. import {talentActivate, talentActivateRsp} from '../proto/game'
  11. import {msgCmd} from '../proto/msg_cmd'
  12. import {GoodsConfig} from '../config/GoodsConfig'
  13. import {UI} from '../enums/UI'
  14. import {DataConfig} from '../config/DataConfig'
  15. import {IOperateNeed, IRole} from '../interface/GlobalInterface'
  16. import {IRoleLevelConfig, RoleLevelConfig} from '../config/RoleLevelConfig'
  17. import {idNum} from '../proto/typedef'
  18. import {RoleQualityConfig} from '../config/RoleQualityConfig'
  19. const {ccclass, property} = cc._decorator
  20. interface ITalentData {
  21. talents: ITalentConfig[]
  22. bigTalent: ITalentConfig
  23. }
  24. enum TALENT_TYPE {
  25. normal = 1,
  26. big,
  27. }
  28. @ccclass
  29. @observer
  30. export default class TalentUI extends BaseUI {
  31. // 用于显示对应天赋的说明
  32. @node('tp/tip')
  33. talTip: cc.Node
  34. @node('tp')
  35. tpAll: cc.Node
  36. // 天赋界面天赋和技能列表 - ScrollView
  37. @list('tal_sv')
  38. talentViewList: List
  39. levelData: ITalentData[] = []
  40. chooseTalent: number
  41. chooseTalentNode: cc.Node
  42. lastBigActiveLv: number = 0
  43. lastActiveLv: number = 0
  44. nextCanActiveSmallID: number = -1
  45. nextCanActiveBigID: number = -1
  46. lastPower: number
  47. /********************** 周期事件 **********************/
  48. // LIFE-CYCLE CALLBACKS:
  49. onLoad() {
  50. // 天赋说明
  51. this.tpAll.active = false
  52. this.levelData.length = 0
  53. let keys = Object.keys(TalentConfig)
  54. let maxLv = 0
  55. for (let i = keys.length - 1; i >= 0; i++) {
  56. if (TalentConfig[keys[i]].talentType == TALENT_TYPE.normal) {
  57. maxLv = TalentConfig[keys[i]].lv
  58. break
  59. }
  60. }
  61. maxLv = DataConfig[DIS_ID.maxLv].data3
  62. this.levelData = new Array(maxLv).fill(null)
  63. for (let key in TalentConfig) {
  64. let cfg = TalentConfig[key]
  65. if (cfg.lv <= maxLv) {
  66. if (!this.levelData[cfg.lv - 1]) this.levelData[cfg.lv - 1] = {talents: [], bigTalent: null}
  67. if (cfg.talentType == TALENT_TYPE.normal) {
  68. this.levelData[cfg.lv - 1].talents.push(cfg)
  69. } else if (cfg.talentType == TALENT_TYPE.big) {
  70. this.levelData[cfg.lv - 1].bigTalent = cfg
  71. }
  72. }
  73. }
  74. this.initMaxBigLv()
  75. }
  76. onEnable() {
  77. Mgr.global.initPower()
  78. this.initNextActiveID()
  79. Mgr.net.add(msgCmd.cmd_talent_activate_rsp, this, this.onTalentActivateRsp)
  80. ccUtils.setLabel('lv.' + Data.user.level, this.node, 'lv_lb')
  81. // 设置玩家当前等级的经验条(0-1之间)
  82. ccUtils.setProgress(Data.user.exp / RanksLevelConfig[Data.user.level].exp, this.node, 'lv_pb')
  83. //前面有一个空节点占位
  84. this.talentViewList.numItems = this.levelData.length + 1
  85. this.talentViewList.scrollTo(this.lastActiveLv - 1 >= 0 ? this.lastActiveLv - 1 : 0)
  86. Mgr.ui.showTop(this, [GOODS.coin, GOODS.diamond, GOODS.talentCoin])
  87. //天赋引导,升级第一个大天赋
  88. Mgr.global.tryShowUserGuide(['12_3'], () => {
  89. this.chooseTalent = Object.values(TalentConfig).find(value => value.talentType == TALENT_TYPE.big).ID
  90. let targetNode = this.talentViewList.content.children.find(v => cc.find('sk', v).active)
  91. this.chooseTalentNode = cc.find('sk', targetNode)
  92. this.onBuyClick()
  93. })
  94. }
  95. onHide() {
  96. this.tpAll.active = false
  97. Mgr.event.removeAll(this)
  98. }
  99. initMaxBigLv() {
  100. this.lastBigActiveLv = 0
  101. this.lastActiveLv = 0
  102. Data.user.talents.forEach(v => {
  103. let cfg = TalentConfig[v]
  104. if (cfg.talentType == TALENT_TYPE.big && cfg.lv > this.lastBigActiveLv) this.lastBigActiveLv = cfg.lv
  105. if (cfg.talentType == TALENT_TYPE.normal && cfg.lv > this.lastActiveLv) this.lastActiveLv = cfg.lv
  106. })
  107. }
  108. initNextActiveID() {
  109. let cfgArr = Mgr.goods.getNextCanActiveTalents()
  110. this.nextCanActiveSmallID = cfgArr[0] ? cfgArr[0].ID : -1
  111. this.nextCanActiveBigID = cfgArr[1] ? cfgArr[1].ID : -1
  112. }
  113. initTalentViewList(node: cc.Node, index: number) {
  114. cc.find('pb', node).active = index < this.lastBigActiveLv
  115. index -= 1
  116. node.children.forEach(v => {
  117. if (v.name != 'pb') {
  118. v.active = index >= 0
  119. }
  120. })
  121. if (index < 0) return
  122. let isMaxLv = index == this.levelData.length - 1
  123. let levelViewData = this.levelData[index]
  124. ccUtils.setLabel((index + 1).toString(), node, 'lv_lb')
  125. let talents = cc.find('s_tal', node).children
  126. // 遍历当前级别所有天赋,判断哪些天赋需要激活
  127. let smallAllActive = true
  128. for (let i = 0; i < talents.length; i++) {
  129. let hasActiveTalent = Data.user.talents.includes(levelViewData.talents[i].ID)
  130. smallAllActive &&= hasActiveTalent
  131. let talent = talents[i]
  132. let isLastTal = i == talents.length - 1
  133. ccUtils.setSpriteGray(!hasActiveTalent, talent, 'icon')
  134. cc.find('bg', talent).active = !(isLastTal && isMaxLv)
  135. cc.find('pb', talent).active = hasActiveTalent && !(isLastTal && isMaxLv)
  136. cc.find('red_dot', talent).active =
  137. levelViewData.talents[i].ID == this.nextCanActiveSmallID &&
  138. Mgr.goods.getOperateNeed(Mgr.goods.getLongIdNumByCfgArr(levelViewData.talents[i].goods)).canUp &&
  139. levelViewData.talents[i].lv <= Data.user.level
  140. this.loadTexImg(`TalentUI/icon/${levelViewData.talents[i].icon}`, talent, 'icon')
  141. talent['cfgID'] = levelViewData.talents[i].ID
  142. }
  143. cc.find('bright_bottom', node).active = smallAllActive
  144. let bigTalent = cc.find('sk', node)
  145. bigTalent.active = !!levelViewData.bigTalent
  146. let hasActiveBigTalent = levelViewData.bigTalent && Data.user.talents.includes(levelViewData.bigTalent.ID)
  147. if (bigTalent.active) {
  148. bigTalent['cfgID'] = levelViewData.bigTalent.ID
  149. cc.find('red_dot', bigTalent).active =
  150. levelViewData.bigTalent.ID == this.nextCanActiveBigID &&
  151. Mgr.goods.getOperateNeed(Mgr.goods.getLongIdNumByCfgArr(levelViewData.bigTalent.goods)).canUp &&
  152. levelViewData.bigTalent.lv <= Data.user.level
  153. this.loadTexImg(`TalentUI/icon/${levelViewData.bigTalent.icon}`, bigTalent, 'icon')
  154. ccUtils.setSpriteGray(!hasActiveBigTalent, bigTalent, 'icon')
  155. }
  156. }
  157. initTalentTip() {
  158. let cfg: ITalentConfig = TalentConfig[this.chooseTalent]
  159. let lvCan = Data.user.level >= cfg.lv
  160. let lastActive = !cfg.condition || Data.user.talents.includes(cfg.condition)
  161. let isActive = Data.user.talents.includes(this.chooseTalent)
  162. cc.find('has', this.talTip).active = isActive
  163. ccUtils.setLabel(Mgr.i18n.getEntryLabel(cfg.entryID), this.talTip, 'scrollView/view/content/label')
  164. let canBuy = cc.find('canBuy', this.talTip)
  165. canBuy.active = !isActive && lvCan && lastActive
  166. if (canBuy.active) {
  167. this.loadTexImg(`Public/goods/${GoodsConfig[cfg.goods[0]].icon}`, canBuy, 'goods_icon')
  168. ccUtils.setLabel(`${Math.toKMBNum(cfg.goods[1])}`, canBuy, 'goods_num')
  169. }
  170. let lock = cc.find('lock', this.talTip)
  171. lock.active = !isActive && (!lvCan || !lastActive)
  172. if (lock.active) {
  173. ccUtils.setLabel(
  174. `${Mgr.i18n.getLabel(lvCan ? LANGUAGE_TYPE.unlockLastTalent : LANGUAGE_TYPE.lvUnlock, [
  175. cfg.lv.toString(),
  176. ])}`,
  177. lock,
  178. 'label',
  179. )
  180. }
  181. }
  182. /********************** 网络事件 **********************/
  183. onTalentActivateRsp(data: talentActivateRsp) {
  184. ccUtils.playAni(
  185. TalentConfig[data.id].talentType == TALENT_TYPE.normal ? 'activeSmall' : 'activeBig',
  186. 0,
  187. this.chooseTalentNode,
  188. 'activeAni',
  189. )
  190. Data.user.talents.push(data.id)
  191. Mgr.global.initTalentAdd()
  192. this.initNextActiveID()
  193. Data.user.roles.forEach(iRole => {
  194. Mgr.global.buildIRole(iRole.hero, iRole)
  195. })
  196. Data.user.cards.forEach(iCard => {
  197. Mgr.global.buildICard(iCard.card, iCard)
  198. })
  199. Mgr.global.updatePower()
  200. this.initMaxBigLv()
  201. this.initTalentTip()
  202. this.tpAll.active = false
  203. this.talentViewList.numItems = this.levelData.length + 1
  204. }
  205. /********************** 触发事件 **********************/
  206. /********************** 点击事件 **********************/
  207. onTalentClick(e) {
  208. // 点击天赋时,弹出天赋说明
  209. this.tpAll.active = true
  210. let node = e.currentTarget
  211. this.chooseTalent = node['cfgID']
  212. this.chooseTalentNode = node
  213. this.initTalentTip()
  214. let cfg: ITalentConfig = TalentConfig[this.chooseTalent]
  215. let pos = ccUtils.convertNode2NodePosAR(node, this.talTip.parent)
  216. let isLeft = pos.x < 500
  217. let bg = cc.find('bg', this.talTip)
  218. bg.scaleX = isLeft ? 1 : -1
  219. bg.x = isLeft ? -12 : 0
  220. this.talTip.setPosition(pos.add(cc.v2(250 * bg.scaleX, cfg.talentType == TALENT_TYPE.normal ? 0 : 20)))
  221. }
  222. onBuyClick() {
  223. if (this.chooseTalent) {
  224. let cfg: ITalentConfig = TalentConfig[this.chooseTalent]
  225. let hasNum = Data.user.goods.get(cfg.goods[0])
  226. if (hasNum >= cfg.goods[1]) {
  227. let data: talentActivate = {id: this.chooseTalent}
  228. Mgr.net.send(msgCmd.cmd_talent_activate, data)
  229. } else {
  230. let idNum = Mgr.goods.getLongIdNumByCfgArr(cfg.goods)
  231. let operate = Mgr.goods.getOperateNeed(idNum)
  232. Mgr.ui.showObtain(operate)
  233. }
  234. }
  235. }
  236. onTipClick() {
  237. // 天赋说明弹框被点击时响应
  238. this.tpAll.active = false
  239. }
  240. }