RecruitUI.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /** @format */
  2. import {UI} from '../enums/UI'
  3. import {BaseUI} from './BaseUI'
  4. import {Data, Mgr} from '../GameControl'
  5. import {ccUtils} from '../utils/ccUtils'
  6. import {observer, render, node, label, editBox, list} from '../mobx/observer'
  7. import {msgCmd} from '../proto/msg_cmd'
  8. import {DIS_ID, EVENT, GOODS, RECRUIT_TYPE, LANGUAGE_TYPE, PREFAB_TYPE, MOD, AD_ID} from '../enums/Enum'
  9. import List from '../uiutils/List'
  10. import {hero, manual, drawInfo, idNum, drawAwardInfo} from '../proto/typedef'
  11. import {drawGetDataRsp, drawRsp} from '../proto/game'
  12. import {HeroescallConfig, IHeroescallConfig} from '../config/HeroescallConfig'
  13. import {CallawardConfig} from '../config/CallawardConfig'
  14. import {RoleConfig} from '../config/RoleConfig'
  15. import {CardConsumeConfig} from '../config/CardConsumeConfig'
  16. import {DataConfig} from '../config/DataConfig'
  17. import {i18nLabel} from '../uiutils/i18nLabel'
  18. import {IReward, IRewardNty, ItemUICfg} from '../interface/UIInterface'
  19. import {SOUND} from '../enums/Sound'
  20. import FrameAnimation from '../uiutils/FrameAnimation'
  21. const {ccclass, property} = cc._decorator
  22. enum DRAW_TYPE { //抽卡类型
  23. rare = 1, //高级英雄
  24. normal = 2, //普通英雄
  25. forging = 3, //装备
  26. }
  27. enum PAY_TYPE { //抽奖付费方式
  28. free = 1,
  29. scroll = 2,
  30. currency = 3,
  31. }
  32. enum IRecruitAnim_TYPE { //动画id
  33. forgingIdle = 'forgingIdle', //锻造待机动画
  34. forge = 'forging', //锻造动画
  35. magicBookIdle = 'magicBookIdle', //高级召唤待机动画
  36. rareSummoning = 'rareSummoning', //高级召唤动画
  37. normalIdle = 'normalIdle', //普通召唤待机动画
  38. normalSummoning = 'normalSummoning', //普通召唤动画
  39. }
  40. interface HEROIC_RANK {
  41. //英雄等级
  42. index: number
  43. color: string
  44. heroI18n: string
  45. equipI18n: string
  46. }
  47. /** 抽卡类型数据 */
  48. interface RecruitType {
  49. id: number
  50. i18n: string
  51. }
  52. interface HeroesCallConfig {
  53. ID: number //奖池
  54. points: number //库ID
  55. type: number //召唤类型
  56. priority: number //显示顺序
  57. quality: number //品质
  58. }
  59. @ccclass
  60. @observer
  61. export class RecruitUI extends BaseUI {
  62. @node('summoning')
  63. summoningNode: cc.Node
  64. @node('summoning/normal')
  65. normalNode: cc.Node
  66. @node('summoning/rare')
  67. rareNode: cc.Node
  68. @node('forging')
  69. forgingNode: cc.Node
  70. @node('summon_list')
  71. summonNode: cc.Node
  72. @node('chain_list')
  73. chainList: cc.Node
  74. @node('forging/ani')
  75. forgingAni: cc.Node
  76. @node('summoning/rare/ani')
  77. rareAni: cc.Node
  78. @node('summoning/normal/ani')
  79. normalAni: cc.Node
  80. @node('quick_ani') //点击快速关闭动画
  81. quickCloseAni: cc.Node
  82. recruitTypeList: RecruitType[] = [
  83. //抽卡功能-抽卡类型
  84. {id: RECRUIT_TYPE.summoning, i18n: LANGUAGE_TYPE.summoning}, //英雄召唤
  85. {id: RECRUIT_TYPE.forging, i18n: LANGUAGE_TYPE.forging}, //装备锻造
  86. ]
  87. RecruitAwardList: drawAwardInfo[]
  88. curSelectType: number = this.recruitTypeList[0].id // 当前选择显示的界面
  89. curShowPublicity: HeroesCallConfig[] = []
  90. normaScrollNum: number //普通卷轴数量
  91. rareScrollNum: number //高级卷轴数量
  92. equipScrollNum: number //锻造卷轴数量
  93. drawNum: number = 10 //一次性连抽数量
  94. hero: drawInfo
  95. hero2: drawInfo
  96. equip: drawInfo
  97. normaDrawGoods: number = DataConfig[DIS_ID.normalSummon].data1 //英雄普通召唤消耗道具
  98. rareDrawGoods: number = DataConfig[DIS_ID.rareSummon].data1 //英雄高级召唤消耗道具
  99. equipFreeNum: number = DataConfig[DIS_ID.equipSummon].data1 //每日免费装备锻造次数
  100. normaDrawNum: number = DataConfig[DIS_ID.normalSummon].data2 //普通召唤-单抽消耗道具数量
  101. rareDrawNum: number = DataConfig[DIS_ID.rareSummon].data2 //高级召唤-单抽消耗道具数量
  102. equipDrawNum: number = DataConfig[DIS_ID.equipSummon].data2 //装备锻造-单抽消耗道具数量
  103. normaFreeNum: number = DataConfig[DIS_ID.normalSummon].data3 //每日免费普通召唤次数
  104. rareDrawLimit: number = DataConfig[DIS_ID.rareSummon].data3 //每日高级召唤次数限制
  105. equipDrawLimit: number = DataConfig[DIS_ID.equipSummon].data3 //每日装备锻造次数限制
  106. normaDrawLimit: number = DataConfig[DIS_ID.normalSummon].data4 //普通召唤每日次数上限
  107. rareTenDraw: number = DataConfig[DIS_ID.rareSummon].data4 //十连高级召唤钻石消耗
  108. equipDrawGoods: number = DataConfig[DIS_ID.equipSummon].data4 //锻造召唤消耗道具
  109. curNormaDraw: number = DataConfig[DIS_ID.normalSummon].data2 //默认单抽数量-会随自己物品数量变动
  110. curRareDraw: number = DataConfig[DIS_ID.rareSummon].data2 //高级召唤-单抽消耗道具数量
  111. curEquipDraw: number = DataConfig[DIS_ID.equipSummon].data2 //默认单抽数量-会随自己物品数量变动
  112. animForging: cc.Animation
  113. animRareSummoning: cc.Animation
  114. animNormalSummoning: cc.Animation
  115. curSummonType: DRAW_TYPE
  116. onShow(args: number = this.recruitTypeList[0].id, fromUI: number) {
  117. //招募引导,招募按钮
  118. cc.find('guide', this.node).active = Mgr.global.tryShowUserGuide(['20_3'])
  119. //抽奖数据
  120. Mgr.net.add(msgCmd.cmd_draw_get_data_rsp, this, this.onDrawGetRsp) //抽奖数据
  121. Mgr.net.add(msgCmd.cmd_draw_rsp, this, this.onDrawRsp)
  122. Mgr.net.send(msgCmd.cmd_draw_get_data)
  123. //从右到左显示货币
  124. Mgr.ui.show(UI.CurrencyUI, [GOODS.diamond, GOODS.coin, GOODS.normalDrawScroll, GOODS.rarelDrawScroll])
  125. this.curSelectType = this.recruitTypeList[0].id // 默认打开第一个界面 不记录玩家上次的留存的记录
  126. this.initShowData()
  127. if (!ccUtils.isEmpty(args)) this.curSelectType = args //默认打开那个界面
  128. this.initAni()
  129. }
  130. initAni() {
  131. this.animForging = this.forgingAni.getComponent(cc.Animation)
  132. this.animRareSummoning = this.rareAni.getComponent(cc.Animation)
  133. this.animNormalSummoning = this.normalAni.getComponent(cc.Animation)
  134. //播放已经暂停的动画
  135. ccUtils.playAni(IRecruitAnim_TYPE.forgingIdle, 0, this.forgingAni)
  136. ccUtils.playAni(IRecruitAnim_TYPE.magicBookIdle, 0, this.rareAni)
  137. ccUtils.playAni(IRecruitAnim_TYPE.normalIdle, 0, this.normalAni)
  138. let initIdle = (tmpAni: cc.Animation, type: IRecruitAnim_TYPE, node: cc.Node) => {
  139. // 为动画添加结束回调
  140. tmpAni.on(
  141. 'finished',
  142. function () {
  143. ccUtils.playAni(type, 0, node)
  144. this.showRewardUI()
  145. },
  146. this,
  147. )
  148. }
  149. initIdle(this.animForging, IRecruitAnim_TYPE.forgingIdle, this.forgingAni) //播放锻造待机动画
  150. initIdle(this.animRareSummoning, IRecruitAnim_TYPE.magicBookIdle, this.rareAni) //播放高级抽卡待机动画
  151. initIdle(this.animNormalSummoning, IRecruitAnim_TYPE.normalIdle, this.normalAni) //播放普通抽卡待机动画
  152. }
  153. onHide(): any {
  154. // 为动画添加结束回调
  155. this.animForging.off('finished')
  156. this.animRareSummoning.off('finished')
  157. this.animNormalSummoning.off('finished')
  158. ccUtils.stopAni(this.forgingAni, IRecruitAnim_TYPE.forge)
  159. ccUtils.stopAni(this.rareAni, IRecruitAnim_TYPE.rareSummoning)
  160. ccUtils.stopAni(this.normalAni, IRecruitAnim_TYPE.normalSummoning)
  161. ccUtils.setTogglesChecked(RECRUIT_TYPE.summoning, this.summonNode)
  162. Mgr.event.removeAll(this)
  163. }
  164. //UI或者其他函数=======================================
  165. //显示界面对应数据
  166. initShowData() {
  167. let diamond = cc.find('btn_diamond/num', this.rareNode)
  168. let normaI18n = cc.find('btn_summoning/lb', this.normalNode)
  169. let rareI18n = cc.find('btn_summoning/lb', this.rareNode)
  170. let equipI18n = cc.find('btn_summoning/lb', this.forgingNode)
  171. this.normaScrollNum = Data.user.goods.get(this.normaDrawGoods)
  172. this.rareScrollNum = Data.user.goods.get(this.rareDrawGoods)
  173. this.equipScrollNum = Data.user.goods.get(this.equipDrawGoods)
  174. let normaStr = this.normaScrollNum >= this.drawNum ? this.drawNum.toString() : this.normaDrawNum.toString()
  175. let rareStr = this.rareScrollNum >= this.drawNum ? this.drawNum.toString() : this.rareDrawNum.toString()
  176. let equipStr = this.equipScrollNum >= this.drawNum ? this.drawNum.toString() : this.equipDrawNum.toString()
  177. normaI18n.getComponent(i18nLabel).setParamByIndex(normaStr, 0)
  178. rareI18n.getComponent(i18nLabel).setParamByIndex(rareStr, 0)
  179. equipI18n.getComponent(i18nLabel).setParamByIndex(equipStr, 0)
  180. this.curNormaDraw = this.normaScrollNum >= this.drawNum ? this.drawNum : this.normaDrawNum
  181. this.curRareDraw = this.rareScrollNum >= this.drawNum ? this.drawNum : this.rareDrawNum
  182. this.curEquipDraw = this.equipScrollNum >= this.drawNum ? this.drawNum : this.equipDrawNum
  183. ccUtils.setColor(Data.user.goods.get(GOODS.diamond) >= this.rareTenDraw ? '#00FF00' : '#FF2525', diamond)
  184. ccUtils.setLabel(this.rareTenDraw.toString(), diamond) //高级召唤十连抽的钻石数量
  185. this.updShowInterface()
  186. }
  187. //刷新界面显示
  188. updShowInterface() {
  189. //显示抽卡界面还是锻造界面
  190. this.summoningNode.active = this.curSelectType == RECRUIT_TYPE.summoning
  191. this.forgingNode.active = this.curSelectType == RECRUIT_TYPE.forging
  192. cc.find('toggle2', this.summonNode).active = Mgr.global.checkModOpen(MOD.equipGet)
  193. this.chainList.children[0].active = Mgr.global.checkModOpen(MOD.equipGet)
  194. ccUtils.setTogglesChecked(this.curSelectType, this.summonNode)
  195. }
  196. //更新当前界面的红点提示
  197. updShowRedDots() {
  198. for (let i = 0; i < this.summonNode.childrenCount; i++) {
  199. let item = this.summonNode.children[i]
  200. if (this.recruitTypeList[i].id == RECRUIT_TYPE.summoning && this.hero2) {
  201. let normalFree = this.normaFreeNum - this.hero2.free //免费次数
  202. //普通英雄抽卡或高级英雄抽卡满足10连抽就提示问题
  203. cc.find('red_dots', item).active =
  204. this.normaScrollNum >= this.drawNum || this.rareScrollNum >= this.drawNum || normalFree > 0
  205. } else if (this.recruitTypeList[i].id == RECRUIT_TYPE.forging && this.equip) {
  206. //装备满足10连抽或者有免费的就提示红点
  207. cc.find('red_dots', item).active =
  208. this.equipFreeNum - this.equip.free > 0 || this.equipScrollNum >= this.drawNum
  209. }
  210. }
  211. cc.find('btn_free/red_dots', this.normalNode).active = this.normaFreeNum - this.hero2.free > 0 //如果普通召唤有免费的就提示十连
  212. cc.find('btn_summoning/red_dots', this.normalNode).active = this.normaScrollNum >= this.drawNum //如果普通召唤的卷轴有十连就提示红点
  213. cc.find('btn_summoning/red_dots', this.rareNode).active = this.rareScrollNum >= this.drawNum //如果高级召唤的卷轴大于10就显示红点
  214. cc.find('btn_free/red_dots', this.forgingNode).active = this.equipFreeNum - this.equip.free > 0 //如果有免费次数就显示红点
  215. cc.find('btn_summoning/red_dots', this.forgingNode).active = this.equipScrollNum >= this.drawNum //如果装备的十连够了就提示红点
  216. //cc.find('btn_free/red_dots', this.forgingNode).active = this.equipFreeNum - this.equip. > 0
  217. }
  218. //更新装备抽奖的保底数量
  219. updEquipNum(list: number[]) {
  220. if (list[0]) cc.find('rarelb', this.forgingNode).getComponent(i18nLabel).setParamByIndex(list[0].toString(), 0)
  221. if (list[1]) cc.find('elitelb', this.forgingNode).getComponent(i18nLabel).setParamByIndex(list[1].toString(), 0)
  222. }
  223. showRewardUI() {
  224. this.quickCloseAni.active = false
  225. let idNumArr: idNum[] = []
  226. let itemUICfgArr: ItemUICfg[] = []
  227. for (let award of this.RecruitAwardList) {
  228. idNumArr.push({id: award.id, num: award.num})
  229. itemUICfgArr.push({changeQuality: award.quality, showDetails: true})
  230. }
  231. let rewardArgs: IReward = {idNumArr, itemUICfgArr}
  232. Mgr.ui.show(UI.RewardUI, rewardArgs)
  233. }
  234. //网络事件=======================================
  235. onDrawGetRsp(data: drawGetDataRsp) {
  236. this.hero2 = data.hero2 ? data.hero2 : drawGetDataRsp.create().hero2
  237. this.hero = data.hero ? data.hero : drawGetDataRsp.create().hero
  238. this.equip = data.equip ? data.equip : drawGetDataRsp.create().equip
  239. let setColor = (num: number, node: cc.Node) => {
  240. ccUtils.setColor(num > 0 ? '#BAFF27' : '#FF2525', node, 'residue_lb')
  241. ccUtils.setLabel(num.toString(), node, 'residue_lb') //剩余次数
  242. }
  243. let setLabel = (str: number, str2: number, node: cc.Node) => {
  244. ccUtils.setLabel((str2 - str).toString(), node, 'summ_residue_lb') //当前抽奖次数
  245. ccUtils.setLabel('/' + str2, node, 'summ_max_lb') //最大抽奖数据
  246. }
  247. setColor(this.normaFreeNum - this.hero2.free, this.normalNode) //免费次数
  248. setColor(this.equipFreeNum - this.equip.free, this.forgingNode) //免费次数
  249. setLabel(this.hero2.daily, this.normaDrawLimit, this.normalNode)
  250. setLabel(this.hero.daily, this.rareDrawLimit, cc.find('lbs', this.rareNode))
  251. setLabel(this.equip.daily, this.equipDrawLimit, this.forgingNode)
  252. if (this.equip.list.length > 0) {
  253. this.updEquipNum(this.equip.list)
  254. }
  255. this.updShowRedDots() //刷新当前界面红点提示
  256. this.updShowInterface() //刷新选中颜色
  257. }
  258. //抽卡结果
  259. onDrawRsp(data: drawRsp, rewardNty: IRewardNty) {
  260. //如果是普通抽奖
  261. if (data.drawType == DRAW_TYPE.normal) {
  262. ccUtils.playAni(IRecruitAnim_TYPE.normalSummoning, 0, this.normalAni)
  263. this.hero2 = data
  264. let normalFree = this.normaFreeNum - this.hero2.free //免费次数
  265. ccUtils.setLabel((this.normaDrawLimit - this.hero2.daily).toString(), this.normalNode, 'summ_residue_lb') //当前抽奖次数
  266. ccUtils.setColor(normalFree > 0 ? '#BAFF27' : '#FF2525', this.normalNode, 'residue_lb')
  267. ccUtils.setLabel(normalFree.toString(), this.normalNode, 'residue_lb') //剩余次数
  268. } else if (data.drawType == DRAW_TYPE.rare) {
  269. ccUtils.playAni(IRecruitAnim_TYPE.rareSummoning, 0, this.rareAni)
  270. this.hero = data
  271. ccUtils.setLabel((this.rareDrawLimit - this.hero.daily).toString(), this.rareNode, 'lbs/summ_residue_lb') //当前抽奖次数
  272. } else if (data.drawType == DRAW_TYPE.forging) {
  273. ccUtils.playAni(IRecruitAnim_TYPE.forge, 0, this.forgingAni)
  274. this.equip = data
  275. let equipFree = this.equipFreeNum - this.equip.free //免费次数
  276. ccUtils.setLabel((this.equipDrawLimit - this.equip.daily).toString(), this.forgingNode, 'summ_residue_lb') //当前抽奖次数
  277. ccUtils.setColor(equipFree > 0 ? '#BAFF27' : '#FF2525', this.forgingNode, 'residue_lb')
  278. ccUtils.setLabel(equipFree.toString(), this.forgingNode, 'residue_lb') //剩余次数
  279. if (this.equip.list.length > 0) {
  280. this.updEquipNum(this.equip.list)
  281. }
  282. }
  283. this.quickCloseAni.active = true
  284. this.initShowData()
  285. this.updShowRedDots() //刷新红点提示
  286. this.RecruitAwardList = data.awardList
  287. }
  288. //触发事件=======================================
  289. // @render
  290. // showRender() {}
  291. // 点击事件=======================================
  292. //英雄抽奖
  293. onClickSummon(event) {
  294. Mgr.audio.playSFX(SOUND.toggleClick)
  295. this.curSelectType = RECRUIT_TYPE.summoning
  296. Mgr.ui.show(UI.CurrencyUI, [GOODS.diamond, GOODS.coin, GOODS.normalDrawScroll, GOODS.rarelDrawScroll])
  297. this.updShowInterface()
  298. }
  299. //装备锻造
  300. onClickForging(event) {
  301. Mgr.audio.playSFX(SOUND.toggleClick)
  302. this.curSelectType = RECRUIT_TYPE.forging
  303. Mgr.ui.show(UI.CurrencyUI, [GOODS.diamond, GOODS.coin, this.equipDrawGoods])
  304. this.updShowInterface()
  305. }
  306. //公示英雄抽卡库
  307. onClickPublicity(event: cc.Button, data: number) {
  308. this.curShowPublicity = []
  309. for (let key in HeroescallConfig) {
  310. let heroCfg = HeroescallConfig[key]
  311. let CallCfg = CallawardConfig[heroCfg.points]
  312. if (heroCfg.type == data && CallCfg && CallCfg.odds > 0) {
  313. this.curShowPublicity.push({
  314. ID: heroCfg.ID,
  315. points: heroCfg.points,
  316. type: heroCfg.type,
  317. priority: CallCfg.priority,
  318. quality: CallCfg.quality,
  319. })
  320. }
  321. }
  322. this.curShowPublicity.sort((a, b) => b.priority - a.priority)
  323. Mgr.ui.show(UI.RecruitPublicityUI, this.curShowPublicity)
  324. }
  325. //免费召唤
  326. onClickFreeNormal(event: cc.Button, data: number) {
  327. this.curSummonType = DRAW_TYPE.normal
  328. Mgr.platform.playVideoAD(AD_ID.summoning, () => {
  329. Mgr.net.send(msgCmd.cmd_draw, {drawType: DRAW_TYPE.normal, payType: PAY_TYPE.free, num: 1})
  330. })
  331. }
  332. //普通卷轴召唤
  333. onClickScrollNormal(event: cc.Button, data: number) {
  334. this.curSummonType = DRAW_TYPE.normal
  335. Mgr.net.send(msgCmd.cmd_draw, {drawType: DRAW_TYPE.normal, payType: PAY_TYPE.scroll, num: this.curNormaDraw})
  336. }
  337. //高级卷轴召唤
  338. onClickScrollRare(event: cc.Button, data: number) {
  339. this.curSummonType = DRAW_TYPE.rare
  340. Mgr.net.send(msgCmd.cmd_draw, {drawType: DRAW_TYPE.rare, payType: PAY_TYPE.scroll, num: this.curRareDraw})
  341. }
  342. //高级钻石召唤
  343. onClickDiamondRare(event: cc.Button, data: number) {
  344. this.curSummonType = DRAW_TYPE.rare
  345. Mgr.net.send(msgCmd.cmd_draw, {drawType: DRAW_TYPE.rare, payType: PAY_TYPE.currency, num: 10})
  346. }
  347. //装备免费召唤
  348. onClickFreeEquip(event: cc.Button, data: number) {
  349. //TODO 免费抽奖需要接入广告sdk
  350. this.curSummonType = DRAW_TYPE.forging
  351. Mgr.audio.playSFX(SOUND.drawEquip)
  352. Mgr.platform.playVideoAD(AD_ID.forging, () => {
  353. Mgr.net.send(msgCmd.cmd_draw, {drawType: DRAW_TYPE.forging, payType: PAY_TYPE.free, num: 1})
  354. })
  355. }
  356. //装备钻石召唤
  357. onClickDiamondEquip(event: cc.Button, data: number) {
  358. this.curSummonType = DRAW_TYPE.forging
  359. Mgr.audio.playSFX(SOUND.drawEquip)
  360. Mgr.net.send(msgCmd.cmd_draw, {drawType: DRAW_TYPE.forging, payType: PAY_TYPE.scroll, num: this.curEquipDraw})
  361. }
  362. //关闭当前正在播放的抽奖动画 切换为待机状态
  363. onClickQuickCloseAni() {
  364. if (this.curSummonType == DRAW_TYPE.forging) {
  365. ccUtils.stopAni(this.forgingAni, IRecruitAnim_TYPE.forge)
  366. ccUtils.playAni(IRecruitAnim_TYPE.forgingIdle, 0, this.forgingAni)
  367. } else if (this.curSummonType == DRAW_TYPE.rare) {
  368. ccUtils.stopAni(this.rareAni, IRecruitAnim_TYPE.rareSummoning)
  369. ccUtils.playAni(IRecruitAnim_TYPE.magicBookIdle, 0, this.rareAni)
  370. } else if (this.curSummonType == DRAW_TYPE.normal) {
  371. ccUtils.stopAni(this.normalAni, IRecruitAnim_TYPE.normalSummoning)
  372. ccUtils.playAni(IRecruitAnim_TYPE.normalIdle, 0, this.normalAni)
  373. }
  374. this.showRewardUI() //提前显示奖励
  375. }
  376. }