//********************* // create by 流云 // time: Fri Nov 28 2025 // desc: //********************* import { _decorator, Component, Node, find, Label, instantiate, Sprite, Button } from 'cc'; import { Auto_wipeOut } from './Auto_wipeOut'; import { ChapterDataManager } from '../../manager/ChapterDataManager'; import { ItemNumType, StatisticsType, TaskType } from '../../game/GameData'; import MTools from 'db://assets/mx/tools/MTools'; import { ItemData } from '../../game/ConfigProjectData'; import { UIID } from '../../game/ConfigRes'; import { itemPic } from '../../com/itemPic'; import { TargetTaskType } from '../../manager/TargetTaskManager'; const { ccclass, property } = _decorator; @ccclass('UIwipeOut') export class UIwipeOut extends Auto_wipeOut { curChapterId: number = 0 adNum = 10 hourTime = 60 * 60 itemShowNum = [] itemGoodNum = [] ishaveLingqu = false /** 挂机预览列表已创建(低帧率时 schedule 单帧可触发多次 onSecond,不能靠 children.length 判断) */ private _guajiRewardListBuilt = false private _onSecondTick = () => this.onSecond(); onLoad(): void { super.onLoad(); } onEnable(): void { super.onEnable(); } onDisable(): void { super.onDisable(); this.unschedule(this._onSecondTick); } onInit(): void { this.hourTime = gg.game.afkTimeOne this._resetRewardViewState(); this.showOpenCenterEff(); this.showOpenMaskEff(2); this.viewInit() } /** 每次 onInit 重置:openPanel 重复打开已显示面板时会再次 onInit,须清掉累积的奖励条目 */ private _resetRewardViewState() { this.ishaveLingqu = false; this._guajiRewardListBuilt = false; this.itemShowNum = []; this.itemGoodNum = []; this._clearLayContentRewards(); } private _clearLayContentRewards() { if (!this.layContent?.isValid) return; const children = this.layContent.children; for (let i = children.length - 1; i >= 0; i--) { children[i].destroy(); } } private _setLingquBtnInteractable(interactable: boolean) { const btn = this.lingquBtn?.getComponent(Button); if (btn) btn.interactable = interactable; const sp = this.lingquBtn?.getComponent(Sprite); if (sp) sp.grayscale = !interactable; } /** * 从配表奖励串构建 ItemData 列表(不依赖 itemGoodNum 缓存,避免 UI 叠层导致重复 push)。 * @param rewardPipe 如 idle_reward / reward:id,num|id,num * @param numMultiplier 挂机为累计小时数 beishuIndex,扫荡为 1 */ private _buildRewardItemListFromConfig(rewardPipe: string, numMultiplier: number): ItemData[] { const itemsArray: ItemData[] = []; const parts = rewardPipe.split('|'); for (let i = 0; i < parts.length; i++) { const seg = parts[i].split(','); const goodId = Number(seg[0]); const baseNum = Number(seg[1]); if (!goodId || !baseNum) continue; const itemNum = baseNum * numMultiplier; if (goodId === 1 || goodId === 2 || goodId === 3 || goodId === 4) { itemsArray.push(new ItemData(goodId, itemNum)); } else if (goodId === 104 || goodId === 105 || goodId === 106 || goodId === 107) { const boxRewardArray = gg.data.getFragmentNumArray(goodId + ',' + itemNum); const statsArray = MTools.mergeToStatsArray(boxRewardArray); for (let j = 0; j < statsArray.length; j++) { const array = statsArray[j].split('|'); itemsArray.push(new ItemData(Number(array[0]), Number(array[1]))); } } } return this._mergeItemDataById(itemsArray); } /** 同 id 奖励合并数量,避免 GetReward 格子重复 */ private _mergeItemDataById(list: ItemData[]): ItemData[] { const countMap = new Map(); for (let i = 0; i < list.length; i++) { const item = list[i]; if (!item?.id) continue; countMap.set(item.id, (countMap.get(item.id) ?? 0) + (item.num ?? 0)); } const merged: ItemData[] = []; for (const [id, num] of countMap) { merged.push(new ItemData(id, num)); } return merged; } viewInit() { let max = ChapterDataManager.getAllChapterAccount() this.curChapterId = gg.data.doc.chapter > max ? max : gg.data.doc.chapter if (this.curChapterId < 2) { this.curChapterId = 2 console.log('当前章节不能扫荡,默认显示第2章') } //获取当前章节-1的配表数据 let chapterConfig = ChapterDataManager.getChapterDataById(this.curChapterId - 1) let config2 = ChapterDataManager.getChapterDataById(gg.game.getChapter(this.curChapterId - 1)); this.zhangjieLab.string = gg.lang.get('第{1}章',[this.curChapterId - 1])+ gg.lang.get(config2.name)//'第' + (this.curChapterId - 1) + '章:' + config2.name this.unschedule(this._onSecondTick); this.schedule(this._onSecondTick, 1); this.refreshBtn() this.refreshItem() this.refreshGuaji() } refreshItem() { //huoquNodes let chapterConfig = ChapterDataManager.getChapterDataById(this.curChapterId - 1) let reward = chapterConfig.idle_reward.split('|'); //this.huoquNodes // let array = [1, 104, 105, 106] let nodeName = ['金币', '绿', '蓝', '紫'] this.huoquNodes.children.forEach((item) => { item.active = false }) // for (let i = 0; i < reward.length; i++) { let rewardData = reward[i].split(',') let goodId = Number(rewardData[0]) let num = Number(rewardData[1]) if (array.indexOf(goodId) != -1) { let index = array.indexOf(goodId) let name = nodeName[index] this.huoquNodes.getChildByName(name).active = true let descLab = this.huoquNodes.getChildByName(name).getChildByName('descLab')?.getComponent(Label) descLab.string = num + gg.lang.get('/小时')//'小时' } } if (reward.length == 3) { this.huoquNodes.x = 80 } else if (reward.length == 4) { this.huoquNodes.x = 0 } } onSecond() { let lastAddTime = gg.data.getStatistics(StatisticsType.AfkRewards); let curTime = gg.data.getCurentTime(); let maxTime = 8 * this.hourTime let time = Math.floor((curTime - lastAddTime) / 1000) if (time >= maxTime) { time = maxTime } const beishuIndex = Math.floor(time / this.hourTime) // 进游戏加载卡顿:单帧 dt 很大时 schedule(1) 会在同一帧连触发多次,旧逻辑会重复 refreshGuaji 叠 item if ((time / this.hourTime) > 1 && !this._guajiRewardListBuilt) { this.refreshGuaji() } else if (this._guajiRewardListBuilt) { this._updateGuajiItemLabels(beishuIndex) } this.prodescLab.string = MTools.formatTimeString(time, "hh:mm:ss"); this.progressBar.progress = time / maxTime } private _updateGuajiItemLabels(beishuIndex: number) { for (let i = 0; i < this.layContent.children.length; i++) { const itemNode = this.layContent.children[i] const lb = itemNode.getChildByName('lb_num')?.getComponent(Label) if (!lb) continue const num = this.itemShowNum[i] if (num == null) continue const _str = 'x' + num * beishuIndex if (lb.string !== _str) { lb.string = _str } } } refreshGuaji() { if (this._guajiRewardListBuilt) { const lastAddTime = gg.data.getStatistics(StatisticsType.AfkRewards); const curTime = gg.data.getCurentTime(); const maxTime = 8 * this.hourTime let time = Math.floor((curTime - lastAddTime) / 1000) if (time >= maxTime) time = maxTime this._updateGuajiItemLabels(Math.floor(time / this.hourTime)) return } this.itemShowNum = []; this.itemGoodNum = []; this._clearLayContentRewards(); //idle_rewards let chapterConfig = ChapterDataManager.getChapterDataById(this.curChapterId - 1) let reward = chapterConfig.idle_reward.split('|') //挂机时长 最长八个小时 let lastAddTime = gg.data.getStatistics(StatisticsType.AfkRewards); let curTime = gg.data.getCurentTime(); let maxTime = 8 * this.hourTime let time = Math.floor((curTime - lastAddTime) / 1000) this.prodescLab.string = MTools.formatTimeString(time, "hh:mm:ss"); this.progressBar.progress = time / maxTime if (time >= this.hourTime) { this.zanwujiangli.active = false if (!this.ishaveLingqu) this._setLingquBtnInteractable(true); //创建奖励Item //layContent //itemNode let beishuIndex = 1 //每个小时*beishuIndex beishuIndex = Math.floor(time / this.hourTime) if (beishuIndex > 8) { beishuIndex = 8 } for (let i = 0; i < reward.length; i++) { let rewardData = reward[i].split(',') let goodId = Number(rewardData[0]) let itemNum = Number(rewardData[1]) let itemNode = instantiate(this.itemNode) itemNode.parent = this.layContent itemNode.active = true itemNode.setPosition(0, 0) itemNode.getComponent(itemPic).setGoodId(goodId) this.itemShowNum.push(itemNum) this.itemGoodNum.push(goodId) itemNode.getChildByName('lb_num').getComponent(Label).string = 'x' + itemNum * beishuIndex + '' } console.log('this.itemShowNum', this.itemGoodNum) this._guajiRewardListBuilt = true } else { this.zanwujiangli.active = true this._setLingquBtnInteractable(false); } } refreshBtn() { let normalCount = gg.data.getStatistics(StatisticsType.saodangNormalCount) let adCount = gg.data.getStatistics(StatisticsType.saodangAdCount) let descNornaml = this.kuaisuBtn.getChildByName('descLab').getComponent(Label) this.kuaisuBtn.getChildByName('tiliLab').getComponent(Label).string = '3'//gg.data.project.vigourCost + '' let descAd = this.kuaisuAdBtn.getChildByName('descLab').getComponent(Label) if (normalCount >= gg.game.getMaxFreeSweepTimes()) { this.kuaisuBtn.active = false this.kuaisuAdBtn.active = true descAd.string = gg.lang.get('次数({1}/{2})',[this.adNum - adCount,this.adNum])//`次数(${this.adNum - adCount}/${this.adNum})` } else { this.kuaisuBtn.active = true this.kuaisuAdBtn.active = false descNornaml.string = gg.lang.get('快速扫荡次数:{1}次',[gg.game.getMaxFreeSweepTimes() - normalCount])//'快速扫荡次数:' + (gg.game.getMaxFreeSweepTimes() - normalCount) + '次' } } click_bgMask() { this.close(2); } click_kuaisuBtn() { //普通扫荡 let spendVigour = 3 let tili = gg.data.getItemNum(ItemNumType.vigour) if (tili < spendVigour) { gg.ui.showToast("体力不足!"); return } let count = gg.data.getStatistics(StatisticsType.saodangNormalCount) if (count >= gg.game.getMaxFreeSweepTimes()) { gg.ui.showToast("今日扫荡已用完,请明日再来!"); return } gg.data.setStatistics(StatisticsType.saodangNormalCount, count + 1) gg.data.subVigour(spendVigour) this.saodangJiangli() this.refreshBtn() } click_lingquBtn() { //领取在线奖励 //挂机时长大于一个小时 重置时间加上一个小时 //gg.data.setStatistics(StatisticsType.AfkRewards, gg.data.getCurentTime()) //200毫秒内点击无法再次响应 if (MTools.beforeTimes(200, "lingquBtn")) { console.log("领取奖励中,请稍后再试"); return }; if (gg.game.afkRewardClaimLock || this.ishaveLingqu) return; if (this.itemShowNum.length > 0 && this.itemGoodNum.length > 0 && this.itemShowNum.length == this.itemGoodNum.length) { // 全局锁:关 wipeOut 动画期间 lingquBtn 仍可点,实例 ishaveLingqu 拦不住第二次 openPanel(GetReward) gg.game.afkRewardClaimLock = true; this.ishaveLingqu = true; this._setLingquBtnInteractable(false); gg.targetTaskManager.statisticalData(TargetTaskType.getHangUpReward, 1); let lastAddTime = gg.data.getStatistics(StatisticsType.AfkRewards); let curTime = gg.data.getCurentTime(); let maxTime = 8 * this.hourTime let time = Math.floor((curTime - lastAddTime) / 1000) if (time >= maxTime) { time = maxTime } const beishuIndex = Math.floor(time / this.hourTime) const chapterConfig = ChapterDataManager.getChapterDataById(this.curChapterId - 1) const itemsArray = this._buildRewardItemListFromConfig(chapterConfig.idle_reward, beishuIndex) if (time >= maxTime) { gg.data.setStatistics(StatisticsType.AfkRewards, gg.data.getCurentTime()) } else { //扣除beishuIndex*60*60秒 gg.data.setStatistics(StatisticsType.AfkRewards, lastAddTime + beishuIndex * this.hourTime * 1000) } gg.ui.openPanel(UIID.GetReward, { data: itemsArray, onClose: () => { gg.game.afkRewardClaimLock = false; }, }); this.close(2) } else { gg.ui.showToast("暂无挂机奖励"); this.close(2) } } click_kuaisuAdBtn() { //AD扫荡 let count = gg.data.getStatistics(StatisticsType.saodangAdCount) if (count >= this.adNum) { gg.ui.showToast("今日扫荡已用完,请明日再来!"); return } gg.sdk.showVideoAd((res) => { if (res) { gg.sdk.reportDY("inLevel", `扫荡-AD-普通扫荡`); gg.data.setStatistics(StatisticsType.saodangAdCount, count + 1) this.saodangJiangli() this.refreshBtn() } else { gg.ui.showToast("观看视频失败"); } }) } saodangJiangli() { gg.targetTaskManager.statisticalData(TargetTaskType.sweep, 1); const chapterConfig = ChapterDataManager.getChapterDataById(this.curChapterId - 1) const itemsArray = this._buildRewardItemListFromConfig(chapterConfig.reward, 1) gg.ui.openPanel(UIID.GetReward, { data: itemsArray, onClose: () => { } }); // } }