import { _decorator, assetManager, Button, Camera, clamp01, Component, director, EventKeyboard, Input, input, instantiate, KeyCode, Label, macro, Node, Prefab, Sprite, sys, tween, v3, Vec2, Vec3, view, Widget } from 'cc'; import { getBattleMapResItem, getBattleMapResItemByChapter, getMainResPakage, getZombieResPakage, ResPkgName, UIConfigs, UIID } from './ConfigRes'; import { UILayer } from '../../mx/module/ui/UIManager'; import { ItemData } from './ConfigProjectData'; import { GEvent } from '../../mx/module/event/GEvent'; import MTools from '../../mx/tools/MTools'; import { OtherDataType, StatisticsType, StatusType } from './GameData'; import { sdkConfig } from '../sdk/sdkConfig'; import { IUserInfo } from './PlayerRecordReporting'; import { BattleType, ChapterDifficulty } from '../manager/ChapterDataManager'; import { BattleCore } from '../ui/BattleGame/BattleCore'; import { MapAgent } from '../ui/BattleGame/MapAgent'; import { BattleDiagnostics } from '../diagnostics/BattleDiagnostics'; import { PfDiagnostics } from '../diagnostics/PfDiagnostics'; import { TetriStackDiagnostics } from '../tetriMap/TetriStackDiagnostics'; import { DEV } from 'cc/env'; import { StoryTypeGroup } from '../storyManager/storyManager'; import { BattleResLoader } from './BattleResLoader'; import { HomeBattlePreload } from './HomeBattlePreload'; import { SmartPreload } from './SmartPreload'; import { BattlePerformance } from '../ui/BattleGame/BattlePerformance'; import { patchSpineSkeletonResetEnums } from '../../mx/module/lang/spineRuntimePatch'; import { UIMainUI } from '../ui/MainUI/UIMainUI'; const { ccclass, property } = _decorator; @ccclass('GameController') export class GameController extends Component { static instance: GameController = null; /**缓存 BattleSuccess 相机 */ private _battleSuccessCamera: Camera | null = null; noGravityWallProbability: number = 0 //无重力方块权重; tetriGameSpeed: number=1 //游戏倍速 最高为3; monsterAttackPercent: number=1; //怪物攻击倍率百分比衰弱 monsterHpPercent: number=1; //怪物血量倍率b百分比衰弱 isShowBlockDrop: boolean = false; isShowWipeOut: boolean = false; /** 挂机收益领取中(防同界面连点;ishaveLingqu 仅本面板实例有效,关面板/异步 openPanel 时拦不住) */ afkRewardClaimLock: boolean = false; //设置关卡不出怪 noMonsterShow: boolean = false; protected onLoad(): void { GameController.instance = this; } private _findNodeByNames(root: Node | null, names: Set): Node | null { if (!root) return null; if (names.has(root.name)) return root; const children = root.children; for (let i = 0; i < children.length; i++) { const found = this._findNodeByNames(children[i], names); if (found) return found; } return null; } /** * 获取 BattleSuccess 使用的相机(优先专用命名,相机不存在时回退到 GameCamera/UICamera)。 */ public getBattleSuccessCamera(): Camera | null { if (this._battleSuccessCamera?.isValid) return this._battleSuccessCamera; const scene = this.node?.scene ?? director.getScene(); const nameSet = new Set([ 'BattleSuccessCamera', 'battleSuccessCamera', 'BattleSuccessCam', 'battleSuccessCam', ]); const cameraNode = this._findNodeByNames(scene, nameSet); const explicitCam = cameraNode?.getComponent(Camera) ?? null; this._battleSuccessCamera = explicitCam ?? gg.ui.GameCamera ?? gg.ui.UICamera ?? null; return this._battleSuccessCamera; } /** * 将 UI 相机下的点击坐标(通常来自 event.getUILocation())转换为 BattleSuccess 相机世界坐标。 * @param uiPos UI 相机坐标(x,y);z 可选,默认 0 * @returns BattleSuccess 相机世界坐标;相机缺失时返回 null */ public convertUIClickToBattleSuccessWorldPos(uiPos: Vec2 | Vec3): Vec3 | null { const srcCam = gg.ui.UICamera ?? gg.ui.GameCamera; const dstCam = this.getBattleSuccessCamera(); if (!srcCam || !dstCam || !uiPos) return null; const uiWorld = new Vec3(uiPos.x, uiPos.y, (uiPos as Vec3).z ?? 0); const screenPos = srcCam.worldToScreen(uiWorld); return dstCam.screenToWorld(screenPos); } /**游戏总时间 */ GameTime: number = 0; /**自己的称谓(主角称呼) */ SelfName: string = "男主"; UserInfo: IUserInfo = null; /**暂停秒赚 */ PauseSecondEarn: boolean = false; /**是否正在播放引导剧情 */ IsPlayingGuideStory: boolean = false; /**是否正在播放新闻 */ IsPlayingNews: boolean = false; /**是否显示障碍物 */ isShowObstacle: boolean = true; /**当前玩家血量 */ playerHp: number = 0; /**当前玩家银币数 */ playerCoinNum: number = 0; //玩家玩过了游戏到结算 IsPlayedGame: boolean = false; playerGameFail: boolean = false; //弹出签到 IsShowSignPop: boolean = false; /**当前完成后的章节 */ finishChapterId: number = -1; /** * 怪物数量倍数 */ monsterNumScale: number = 1; playerWeaponIdArray = [] playerSkillIdArray = [] playerSkillGroupIdArray = [] playerWeaponGroupIdArray = [] setPlayerSkillGroupIdArray = false setPlayerWeaponGroupIdArray = false afkTimeOne = 60 * 60 /**武器模式最大挑战次数 */ // WeaponCountMax = 5; // /**无尽模式最大挑战次数 */ // InfiniteChallengeCountMax = 20; // /**道具模式最大挑战次数 */ // PropModeCountMax = 20; // /**宝箱副本最大挑战次数 */ // BoxChallengeCountMax = 20; // /**抽卡挑战模式最大挑战次数 */ // GachaChallengeCountMax = 20; // /**boss挑战模式最大挑战次数 */ // BossChallengeCountMax = 20; isInitAllData: boolean = false /**当前选中准备进入的战斗章节id */ CurentSelectChapterId: number = 1; /**当前选中准备进入的战斗模式 */ CurentSelectBattleType: BattleType = BattleType.Level; /**当前选中准备进入的战斗难度 */ CurentSelectBattleDifficulty: ChapterDifficulty = ChapterDifficulty.Normal; /**当前选中的副本 */ CurentSelectReplica: ITableReplica = null; /**当前正在进行中的战斗 */ CurentBattle: BattleCore = null; /** 正在离开战斗回大厅:局内 update 应直接 return,且暂不置空 CurentBattle */ private _battleLeaving = false; /** 局内逻辑是否仍有效(离开战斗/清引用过程中为 false,避免刷 null 报错) */ isBattleContextActive(): boolean { return !this._battleLeaving && this.CurentBattle != null; } guideStoryId: number = 1; /** 第4章结束剧情后:角色升级引导完成时再弹丧尸农场入口(原剧情内 guide4) */ pendingFarmGuideAfterCh4Role: boolean = false; /** 下一次 homeGuideIndex==4 时强制出「点角色」遮罩(第三章后剧情触发,不依赖 doc.chapter 判档) */ forceHomeRoleTabGuide: boolean = false; guideGreatGift: boolean = false; curChooseZombieType: string = 'farm' //农场,工厂,矿产 /**第三章失败引导角色升级 */ thirdChapterFailRoleUpgrade: boolean = false; /**第三章失败引导武器升级 */ thirdChapterFailWeaponUpgrade: boolean = false; /***第三章胜利榴莲弹出 */ thirdChapterWinGreatGift: boolean = false; /**商店首日登录刷新*/ isShopFirstLoginRefresh: boolean = false; /** * 初始化游戏 */ async init() { console.log("开始初始化game"); patchSpineSkeletonResetEnums(); macro.ENABLE_MULTI_TOUCH = false this.GameTime = 0; gg.dot.init(); gg.audio.MuteMusic = gg.data.getStatus(StatusType.MuteMusic) == 1; gg.audio.MuteEffect = gg.data.getStatus(StatusType.MuteEffect) == 1; GEvent.Ins.on(GEvent.UpdateItemNum, this.onItemUpdate, this); // this.playerWeaponIdArray.push(22); // let obj: IBattleSkill = { // weaponId: 22, // id: 2105, // type: 1, // limit_num: 10, // }; // this.playerSkillIdArray.push(obj); // obj = { // weaponId: 22, // id: 2153, // type: 1, // limit_num: 10, // }; // this.playerSkillIdArray.push(obj); this.unscheduleAllCallbacks(); //初始化每整秒更新计时器 this.schedule(() => { this.onSecond(); }, 1); // gg.data.project.setHaveWeaponIds([1,2,3,4,5,6,7,8,20]); //首次登录 if (gg.data.IsFirstLogin) { console.log('首次登录') gg.sdk.reportDY("inLevel", "进入-首次登录"); //测试-设置体力金币钻石战力等 gg.data.setCombatPower(50); gg.data.setMoney(100); //初始化30 gg.data.setVigour(30); gg.data.setDiamond(10); //测试-设置章节为第2章 gg.data.doc.chapter = 1 //测试-送8个已装备 //测试-送8个已装备 gg.data.project.setHaveWeaponIds([1,2,3,4,5,6,7,8]); gg.data.project.setEquipWeaponStatus([1,2,3,4,5,6,7,8]); gg.data.setStatistics(StatisticsType.ShopBuyGoldAdCount, 6) gg.data.setStatistics(StatisticsType.ShopBuyItemAdCount, 6) gg.data.setStatistics(StatisticsType.FreeBoxCount, 0) gg.data.setStringData(OtherDataType.SignData, '0&0&1') gg.data.setStatistics(StatisticsType.ActiveRefreshPurpleCount, 2) gg.data.setStatistics(StatisticsType.NoDoublePurpleSkillInterval, 50) gg.data.setStringData(OtherDataType.UserLevelupData, '0&10&0&0&0&0&0') gg.data.setStringData(OtherDataType.TaskRewardGetData, '0&0&0&0&0') gg.data.setStringData(OtherDataType.DayTaskRewardGetData, '0&0&0&0&0') gg.data.setStringData(OtherDataType.DayTaskProgressData, '0&0&0&0&0&0&0&0&0&0&0&0&0&0') gg.data.setStringData(OtherDataType.DayActiveGetRewardData, '0&0&0&0&0&0&0&0&0&0&0&0&0&0') // gg.role.setDefaultSkin(); gg.data.setStatistics(StatisticsType.NoDoublePurpleSkillCount, 8); gg.data.project.vigourCost = 0; } else { gg.sdk.reportDY("inLevel", "进入-第" + gg.data.LoginDays + "天登录"); } let arr = gg.data.project.getHaveWeaponIds(); if (arr.length == 0) { gg.data.project.setHaveWeaponIds([1, 2, 4, 5, 6, 7, 9, 11]); gg.data.project.setEquipWeaponStatus([1, 2, 4, 5, 6, 7, 9, 11]); } //今天首次登录 if (gg.data.IsFirstLoginToday) { gg.game.isShopFirstLoginRefresh = true; } // let list = gg.storyManager.getStoryComicData(StoryTypeGroup.chushiComic); // let isCanOpen = gg.storyManager.isCanOpen(StoryTypeGroup.chushiComic); if (gg.data.IsFirstLogin) { // gg.audio.playMusic({ name: "主页背景音", path: "bgm/" }); // gg.storyManager.storyGuide(StoryTypeGroup.chushiComic) gg.game.CurentSelectReplica = null; gg.game.CurentSelectChapterId = 1; gg.game.CurentSelectBattleType = BattleType.Level; gg.game.CurentSelectBattleDifficulty = ChapterDifficulty.Normal; // 首登流程跑完再标记,避免本会话后续重复发奖;小游戏 restart 依赖存档 status=0 再次进入本分支 gg.data.markFirstLoginCompleted(); } gg.data.saveToServer(); if (gg.data.doc.chapter == 1) { gg.data.project.vigourCost = 0 this.enterBattle() } else { await BattleResLoader.ensureHallBundles(); this.enterMain(); } gg.sdk.reportDY("inLevel", `加载耗时-资源加载完成_${Math.floor(sdkConfig.resLoadFinishTime / 1000)}s`) gg.sdk.reportDY("inLevel", `加载耗时-sdk加载完成_${Math.floor(sdkConfig.sdkLoadFinishTime / 1000)}s`) this.isInitAllData = true console.log("初始化game完成"); this.scheduleOnce(() => { let getLaunchOptionsSync = gg.sdk.getLaunchOptionsSync_custom() console.log('getLaunchOptionsSync', JSON.stringify(getLaunchOptionsSync)) if (getLaunchOptionsSync && getLaunchOptionsSync.scene && String(getLaunchOptionsSync.scene).includes('3041')) { const channel = (getLaunchOptionsSync.query as { feed_game_channel?: string | number } | null | undefined)?.feed_game_channel; if (channel == 1) { gg.sdk.PlatformReportScene() gg.sdk.reportDY("inLevel", `推荐流-复访用户`); //离线收益场景 //this.showOutGame() } else if (channel == 2) { gg.sdk.PlatformReportScene() gg.sdk.reportDY("inLevel", `推荐流-获客用户`); } } else { //this.showOutGame() } }, 0.2) gg.targetTaskManager.initCurTargetTaskConfig() } /** * 获取章节id(取服务器端控制的章节id) * @param chapterID 章节ID * @returns 章节数据 */ getChapter(chapterID) { if (gg.sdk.levelS.length > chapterID - 1) return gg.sdk.levelS[chapterID - 1]; return chapterID; } /**获取原始章节id */ getOriginChapterID(chapterID) { let idx = gg.sdk.levelS.findIndex((id) => id == chapterID); if (idx >= 0) return idx + 1; return chapterID; } /** * 重置游戏 */ reset(tagStr: string = '') { gg.data.reset((res) => { if (res) { if (gg.sdk.pf) { assetManager.cacheManager.clearCache(); gg.sdk.pf["restartMiniProgramSync"](); } else { this.playerHp = 0; this.playerCoinNum = 0; this.isShowObstacle = true this.monsterNumScale = 1; this.playerWeaponIdArray = [] this.playerSkillIdArray = [] this.playerSkillGroupIdArray = [] this.playerWeaponGroupIdArray = [] this.setPlayerSkillGroupIdArray = false this.setPlayerWeaponGroupIdArray = false gg.game.CurentSelectBattleType = 1 this.unscheduleAllCallbacks(); GEvent.Ins.off(GEvent.UpdateItemNum, this.onItemUpdate, this); gg.ui.closeAllPanel(); // gg.task.init(); setTimeout(() => { this.init(); }, 10); } } else { gg.ui.showToast("重置游戏失败"); } }, tagStr); } /** * 每帧更新 * @param deltaTime */ update(deltaTime: number) { this.GameTime += deltaTime; } /** * 每秒更新逻辑 */ onSecond() { //游戏总整秒数 let gs = Math.floor(this.GameTime); let onlineTime = Math.floor(gg.data.OnlineTimeForAll); //每3分钟打点 if (Math.floor(onlineTime) % 60 == 0) { let index = Math.floor(onlineTime / 60); if (index == 1 || index == 2) { gg.sdk.reportDY("inLevel", `累积时长-${index}分钟`); } } if (Math.floor(onlineTime) % 180 == 0) { let index = Math.floor(onlineTime / 60); gg.sdk.reportDY("inLevel", `累积时长-${index}分钟`); } //每分钟执行的逻辑 if (gs % 60 == 0) { } GEvent.Ins.emit(GEvent.SecondUpdate); } /** * 物品更新 */ onItemUpdate() { } /** * 回大厅/主界面时释放战斗阶段累积的静态缓存(与 enterMain 配套)。 */ private releaseStaticCachesLeavingBattle(): void { BattleDiagnostics.resetBattle(); TetriStackDiagnostics.resetBattle(); PfDiagnostics.resetBattleSession(); BattlePerformance.resetMemoryPressure(); this.CurentBattle = null; MapAgent.clearStaticWallPointPool(); MTools.clearBeforeTimesMapForEnterHall(); } /** 离开战斗:先标记结束并关面板,再清全局引用(避免 update 访问 null) */ private leaveBattleToHall(): void { this._battleLeaving = true; const battle = this.CurentBattle; if (battle) { battle.IsGameOver = true; battle.shutdownBattlePhysicsForLeave(); } } private finishLeaveBattleCleanup(): void { this.releaseStaticCachesLeavingBattle(); this._battleLeaving = false; } /** * 进入主场景 */ enterMain(pageeID: UIID = UIID.Home) { gg.ui.clearWaitPopQueue(); this.leaveBattleToHall(); const hasMainUI = gg.ui.hasPanel(UIID.MainUI); void this._returnToMainUI(pageeID, hasMainUI); } /** 离开战斗后统一释放内存并打开大厅(只卸战斗内存,不删磁盘缓存) */ private async _returnToMainUI(pageeID: UIID, hasMainUI: boolean): Promise { if (!hasMainUI) { this.showLoading(1); } const startTime = new Date().getTime(); await gg.ui.closeAllPanelAsync(); gg.ui.clearAnimFlyNodes(); this.finishLeaveBattleCleanup(); gg.res.clearResPkg(ResPkgName.BattleRes); gg.res.clearNodePool(); BattleResLoader.releaseBattleBundles(); if (!hasMainUI) { await BattleResLoader.ensureHallBundles(); await new Promise((resolve) => { gg.res.loadResPakg(getMainResPakage(), (c, t) => { if (DEV) { console.log("加载主场景资源", c, t); } }, () => resolve()); }); } await gg.ui.openPanel(UIID.MainUI, { data: pageeID }); // 智能预载接管:邻接 Tab + 战斗包错峰 SmartPreload.onMainTab(pageeID || UIID.Home); if (!hasMainUI) { sdkConfig.enterHallTime = new Date().getTime() - startTime; gg.sdk.reportDY("inLevel", `加载耗时-进入大厅_${Math.floor(sdkConfig.enterHallTime / 1000)}s`); this.hideLoading(); } } /** * 加载战斗分包与核心 prefab,完成后打开战斗界面。 * weapon1 单预制体很快,可 await 保证首枪就绪;地图与开界面并行预热。 * 体感慢主要来自:回大厅卸分包导致二次冷启动、局内地图 ensure,而不是 weapon1。 */ private async loadBattleAndOpen(panelId: UIID, onLoaded?: () => void): Promise { await BattleResLoader.ensureBattleEntry(); await BattleResLoader.ensureBattleCoreBundles(); const mapId = gg.game.CurentBattle?.MapId; const mapItem = mapId ? getBattleMapResItem(mapId) : null; if (mapItem) { await gg.res.ensurePrefab(mapItem.name, mapItem.path, mapItem.bundle); } // 单个 weapon1 + hitEffect,耗时通常远小于地图/界面;await 可避免首枪空等 await BattleResLoader.preloadWeapon1Bullet(); await gg.ui.openPanel(panelId); const duration = new Date().getTime() - sdkConfig.enterBattleTime; console.log("章节进入-战斗场景加载完成", duration + "ms"); gg.sdk.reportDY("inLevel", `章节进入-战斗场景加载完成`); onLoaded?.(); } /** * 进入战斗场景 */ enterBattle(notCheckPower = false) { //检查有没有装备八个武器 gg.game.IsPlayedGame = false gg.game.playerGameFail = false let equippedArr = gg.data.project.getEquippedWeaponDataList(); if (equippedArr.length < 8) { gg.ui.showToast('需装备8个武器!') return 0; } //检查体力是否足够 if (!gg.data.project.checkVigourEnough(this.CurentSelectBattleType) && gg.data.doc.chapter != 1 ) { gg.ui.openPanel(UIID.buyPower); return 0; } if (!notCheckPower && !gg.data.project.checkPowerEnough(this.CurentSelectChapterId, this.CurentSelectBattleType, this.CurentSelectBattleDifficulty) && !notCheckPower) { //战力不足 gg.ui.openPanel(UIID.challengeTip, { data: () => { this.enterBattle(true); } }) return 2; } if(gg.data.doc.chapter == 1){ //不扣体力 console.log("第1关,不扣体力"); }else{ gg.data.subVigour(gg.data.project.vigourCost); } this.showLoading(1); //清除_wait_popIds队列 SmartPreload.pause(); HomeBattlePreload.pause(); gg.ui.clearWaitPopQueue(); gg.ui.closeAllPanel(); gg.ui.clearAnimFlyNodes(); sdkConfig.enterBattleTime = new Date().getTime(); BattleDiagnostics.resetBattle(); TetriStackDiagnostics.resetBattle(); PfDiagnostics.resetBattleSession(); this.CurentBattle = new BattleCore(); this.CurentBattle.init(); if(gg.game.CurentSelectBattleType == BattleType.OrangeWeaponMode_Ya){ //进入救救我鸭的副本 gg.sdk.reportDY("inLevel", `章节进入-战斗场景加载中`); this.scheduleOnce(() => { void this.loadBattleAndOpen(UIID.jiujiuwoyaGame); }) }else{ gg.sdk.reportDY("inLevel", `章节进入-战斗场景加载中`); this.scheduleOnce(() => { void this.loadBattleAndOpen(UIID.TetriGame); }) } return 1; } /** * 获取所有秒赚 * @returns */ getAllProfit() { let num = 0; return Math.floor(num); } /** * 弹出道具不足弹窗 * @param skipUIidArr 需要跳转的UIID数组 * @param itemID 道具id * @param itemNum 道具数量 * @param showVideoAd 是否显示视频广告获取 * @returns */ showSkipPop(itemID = 0, itemNum = 1, showVideoAd = false, skipUIidArr: UIID[] = [], title = "道具不足") { gg.ui.openPanel(UIID.SkipPop, { data: { skipUIidArr: skipUIidArr, itemID: itemID, itemNum: itemNum, showVideoAd: showVideoAd, title: title } }); } async getUserInfo() { this.UserInfo = (await gg.sdk.getUserInfo()) as IUserInfo; if (this.UserInfo) { gg.data.doc.uid = this.UserInfo.nickName; } } async showMsgBox(content: string, title: string = "温馨提示", yesFun: Function = null, noFun: Function = null) { gg.ui.openPanel(UIID.MsgBox, { data: { title: title, content: content, yesFun: yesFun, noFun: noFun } }) } /**获取最大免费扫荡次数 */ getMaxFreeSweepTimes() { let count = 3; //count += gg.purchase.getFreeSweepTimes(); return count; } /**根据奖励字符串解析奖励道具(只能解析固定格式的字符串:“道具id,道具数量|道具id,道具数量|...”) */ parseRewardStr(rewardStr: string) { let rewardArr = rewardStr.split("|"); let rewardList: ItemData[] = []; for (let i = 0; i < rewardArr.length; i++) { let str = rewardArr[i]; if (str == "") continue; let [id, num] = rewardArr[i].split(","); let itemData = new ItemData(Number(id), Number(num)); itemData.staticData = gg.data.table.getItemData(Number(id)); itemData.isFragment = itemData.staticData.type == 8; rewardList.push(itemData); } return rewardList; } /**根据道具数组合并同类型道具 */ mergeSameTypeItem(itemList: ItemData[]) { let itemMap = new Map(); for (let i = 0; i < itemList.length; i++) { let item = itemList[i]; if (itemMap.has(item.id)) { itemMap.get(item.id).num += item.num; } else { itemMap.set(item.id, item); } } return Array.from(itemMap.values()); } /**根据道具数组自动获得通用碎片转化的道具 */ autoMergeFragment(itemList: ItemData[]) { let fragmentList = itemList.filter(x => x.staticData.type == 4); if (fragmentList.length == 0) return itemList; let resultArr = []; //增加碎片,相当于开了个宝箱一样给对应数量的碎片 for (let i = 0; i < fragmentList.length; i++) { let fragment = fragmentList[i]; let boxRewardArray = gg.data.getFragmentNumArray(fragment.id + ',' + fragment.num) let statsArray = MTools.mergeToStatsArray(boxRewardArray) for (let i = 0; i < statsArray.length; i++) { let array = statsArray[i].split('|') let item = new ItemData(Number(array[0]), Number(array[1])) item.num = Number(array[1]) item.id = Number(array[0]) resultArr.push(item); } } return resultArr; } getRoleLv() { let curData = gg.data.getStringData(OtherDataType.UserLevelupData) let curDataArr = curData.split('&') let roleLevel = curDataArr[0] return Number(roleLevel); } /**根据奖励字符串显示获得奖励界面 */ showGetRewardByReardStr(rewardStr: string, callBack=null) { let rewardsStrArr = rewardStr.split("|"); //直接增加 let itemsArray = []; for (let i = 0; i < rewardsStrArr.length; i++) { let signReward = rewardsStrArr[i] let [id, num] = signReward.split(","); let itemData = gg.data.table.getItemData(Number(id)); if (itemData.type == 8) { //给个武器 let item = new ItemData(itemData.weapon_type, Number(num)) item.num = Number(num) item.id = itemData.weapon_type item.isFragment = true itemsArray.push(item) } else if (itemData.type == 4) { //增加碎片,相当于开了个宝箱一样给对应数量的碎片 let boxRewardArray = gg.data.getFragmentNumArray(id + ',' + num) let statsArray = MTools.mergeToStatsArray(boxRewardArray) for (let i = 0; i < statsArray.length; i++) { let array = statsArray[i].split('|') let item = new ItemData(Number(array[0]), Number(array[1])) item.num = Number(array[1]) item.id = Number(array[0]) itemsArray.push(item); } } else if (itemData.type == 5) { //转换为对应性别的皮肤 let itemid = gg.role.getSkinItemIdFromReward(Number(id)); if (itemid) { id = itemid.toString(); } } else { let item = new ItemData(id, Number(num)) item.num = Number(num); item.staticData = itemData itemsArray.push(item) } } if(callBack){ gg.ui.openPanel(UIID.GetReward, { data: itemsArray, onClose: callBack }); }else{ gg.ui.openPanel(UIID.GetReward, { data: itemsArray }); } } showGetRewardByItemList(items: ItemData[]) { //直接增加 let itemsArray = []; for (let i = 0; i < items.length; i++) { let itemData = items[i]; if (!itemData.staticData) itemData.staticData = gg.data.table.getItemData(itemData.id); if (itemData.staticData && itemData.staticData.type == 8) { //给个武器 let item = new ItemData(itemData.staticData.weapon_type, Number(itemData.num)) item.num = Number(itemData.num) item.id = itemData.staticData.weapon_type item.isFragment = true itemsArray.push(item) } else if (itemData.staticData && itemData.staticData.type == 4) { //增加碎片,相当于开了个宝箱一样给对应数量的碎片 let boxRewardArray = gg.data.getFragmentNumArray(itemData.staticData.id + ',' + itemData.num) let statsArray = MTools.mergeToStatsArray(boxRewardArray) for (let i = 0; i < statsArray.length; i++) { let array = statsArray[i].split('|') let item = new ItemData(Number(array[0]), Number(array[1])) item.num = Number(array[1]) item.id = Number(array[0]) itemsArray.push(item); } } else { itemsArray.push(itemData) } } gg.ui.openPanel(UIID.GetReward, { data: itemsArray }); } showLoading(index: number = 2) { GEvent.Ins.emit(GEvent.SHOW_LOADING, index); } hideLoading() { GEvent.Ins.emit(GEvent.HIDE_LOADING); } /**根据 id 跳转主界面 Tab;已在大厅时仅切页,否则走 enterMain 回厅流程 */ gotoPageById(id: UIID): void { const cfg = UIConfigs[id]; if (!cfg || cfg.layer !== UILayer.MainUI) { return; } if (this.switchMainTabIfInHall(id)) { return; } this.enterMain(id); } /** 任务等统一跳转:主 Tab 切页,弹窗叠层打开,丧尸页先拉资源 */ gotoTaskJump(pageID: UIID): void { const cfg = UIConfigs[pageID]; if (!cfg) { console.warn('[gotoTaskJump] unknown pageID', pageID); return; } if (cfg.layer === UILayer.MainUI) { this.gotoPageById(pageID); return; } if (pageID === UIID.zombieLayer) { this.showLoading(1); const resPkg = getZombieResPakage(); gg.res.loadResPakg(resPkg, null, () => { this.hideLoading(); gg.ui.openPanel(UIID.zombieLayer); }); return; } if (gg.ui.hasPanel(UIID.MainUI)) { gg.ui.openPanel(pageID); return; } this.enterMain(UIID.Home); this.scheduleOnce(() => gg.ui.openPanel(pageID), 0.5); } /** 已打开 MainUI 时切换底部 Tab,避免误走 enterMain 关闭全部面板 */ switchMainTabIfInHall(pageID: UIID): boolean { if (!gg.ui.hasPanel(UIID.MainUI)) { return false; } const mainUI = UIMainUI.resolveShell(); if (!mainUI?.isValid) { return false; } void mainUI.showPage(pageID); return true; } onLoadingShow(c: number, t: number) { this.CurentLoadingProgress = clamp01(c / t); console.log("onLoadingShow", c, t); } CurentLoadingProgress: number = 0; isPreLoadChapterRes: boolean = false; private _pendingPreLoadChapterId: number = 0; private _runningPreLoadChapterId: number = 0; /**预加载当前章节所需要的资源 */ preLoadChapterRes(chapterID: number) { this.scheduleOnce(() => { void (async () => { await BattleResLoader.ensureBattleEntry(); const mapItem = getBattleMapResItemByChapter(chapterID); if (!mapItem) { return; } // 局内/结算叠层时禁止 clearResPkg(BattleRes),否则会释放场上仍在渲染的 prefab/贴图 if (gg.game.CurentBattle) { await gg.res.ensurePrefab(mapItem.name, mapItem.path, mapItem.bundle); gg.res.appendToResPkg(ResPkgName.BattleRes, [mapItem]); return; } gg.res.loadResPakg({ name: ResPkgName.BattleRes, isReleaseable: true, ress: [mapItem], }, null, () => { /* 不主动 triggerGC */ }); })(); }) } }