import { _decorator, Label, Node, tween, Vec3, Color, Sprite, Tween } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { GameEvent } from "../common/config/GameEvent"; import { talConf, ItalConf } from "../common/config/TalSet"; import { CanSelectHeros, HeroInfo } from "../common/config/heroSet"; import { CanSelectSkills, SkillSet } from "../common/config/SkillSet"; import { ItemSet } from "../common/config/ItemSet"; import { smc } from "../common/SingletonModuleComp"; import { CardType } from "../common/config/GameSet"; const { ccclass, property } = _decorator; /** 视图层对象 */ @ccclass('MissionCardComp') @ecs.register('MissionCard', false) export class MissionCardComp extends CCComp { /** 视图层逻辑代码分离演示 */ @property(Node) card1:Node = null! @property(Node) card2:Node = null! @property(Node) card3:Node = null! @property(Node) card4:Node = null! @property(Node) btnClose: Node = null! @property(Node) Lock: Node = null! card1_data:any = null! card2_data:any = null! card3_data:any = null! card4_data:any = null! // 当前卡片类型 curCardType: CardType = CardType.Talent; // 已购买的卡片槽位标记 (用于物品购买) purchasedSlots: boolean[] = [false, false, false, false, false]; onLoad() { oops.message.on(GameEvent.TalentSelect, this.onTalentSelect, this); oops.message.on(GameEvent.HeroSkillSelect, this.onHeroSkillSelect, this); oops.message.on(GameEvent.ShopOpen, this.onShopOpen, this); oops.message.on(GameEvent.MissionStart, this.onMissionStart, this); oops.message.on(GameEvent.MissionEnd, this.onMissionEnd, this); oops.message.on(GameEvent.ToCallFriend, this.onCallFriend, this); } onDestroy() { oops.message.off(GameEvent.TalentSelect, this.onTalentSelect, this); oops.message.off(GameEvent.HeroSkillSelect, this.onHeroSkillSelect, this); oops.message.off(GameEvent.ShopOpen, this.onShopOpen, this); oops.message.off(GameEvent.MissionStart, this.onMissionStart, this); oops.message.off(GameEvent.MissionEnd, this.onMissionEnd, this); oops.message.off(GameEvent.ToCallFriend, this.onCallFriend, this); this.ent.destroy(); } init(){ this.onMissionStart(); } /** 游戏开始初始化 */ onMissionStart() { this.Lock.active = true; this.eventQueue = []; } /** 游戏结束清理 */ onMissionEnd() { this.eventQueue = []; this.node.active = false; this.hasSelected = false; // 停止所有卡片动画 const cards = [this.card1, this.card2, this.card3, this.card4]; cards.forEach(card => { if (card) { Tween.stopAllByTarget(card); const selected = card.getChildByName("selected"); if (selected) Tween.stopAllByTarget(selected); } }); } start() { // 初始隐藏或显示逻辑 this.node.active = false; this.resetCardStates(); } private resetCardStates() { const cards = [this.card1, this.card2, this.card3, this.card4]; cards.forEach(card => { if (card) { const selected = card.getChildByName("selected"); if (selected) selected.active = false; // 恢复缩放和颜色 card.setScale(1, 1, 1); const sprite = card.getComponent(Sprite); if (sprite) sprite.color = new Color(255, 255, 255); } }); // 重置购买状态 this.purchasedSlots = [false, false, false, false, false]; } // 是否已经选择了天赋 private hasSelected: boolean = false; // 事件队列 private eventQueue: CardType[] = []; private onShopOpen(event: string, args: any) { this.eventQueue.push(CardType.Potion); this.checkQueue(); } private onTalentSelect(event: string, args: any) { this.eventQueue.push(CardType.Talent); this.checkQueue(); } private onHeroSkillSelect(event: string, args: any) { this.eventQueue.push(CardType.Skill); this.checkQueue(); } private onCallFriend(event: string, args: any) { this.eventQueue.push(CardType.Partner); this.checkQueue(); } private checkQueue() { if (this.node.active) return; if (this.eventQueue.length === 0) return; const type = this.eventQueue.shift(); if (type) { this.showCardType(type); } } private showCardType(type: CardType) { this.node.active = true; this.hasSelected = false; this.curCardType = type; this.resetCardStates(); this.refCards(); this.playShowAnimation(); } private playShowAnimation() { const cards = [this.card1, this.card2, this.card3, this.card4]; cards.forEach((card, index) => { if (card) { card.setScale(Vec3.ZERO); tween(card) .delay(index * 0.1) .to(0.4, { scale: new Vec3(1, 1, 1) }, { easing: 'backOut' }) .start(); } }); } refCards(){ // 根据当前类型获取数据 let allData: any[] = []; if (this.curCardType === CardType.Talent) { allData = Object.values(talConf); } else if (this.curCardType === CardType.Skill) { // 过滤掉怪物技能 (uuid >= 6200) // allData = Object.values(SkillSet).filter((s:any) => s.uuid < 6200); allData = CanSelectSkills.map(id => SkillSet[id]); } else if (this.curCardType === CardType.Partner) { allData = CanSelectHeros.map(id => HeroInfo[id]); } // 后续扩展其他类型 // else if (this.curCardType === CardType.Skill) { ... } const result: any[] = []; const temp = [...allData]; // 简单的随机抽取算法 for (let i = 0; i < 4 && temp.length > 0; i++) { const index = Math.floor(Math.random() * temp.length); result.push(temp[index]); temp.splice(index, 1); } // 更新卡片 if (result.length > 0) this.updateCardData(1, result[0]); if (result.length > 1) this.updateCardData(2, result[1]); if (result.length > 2) this.updateCardData(3, result[2]); if (result.length > 3) this.updateCardData(4, result[3]); } updateCardInfo(card:Node, data:any){ if(!card) return card.active = true; // 隐藏选中状态 const selected = card.getChildByName("selected"); if(selected) selected.active = false; let name = card.getChildByName("name") if(name){ name.getComponent(Label)!.string = data.name } let info = card.getChildByName("info")?.getChildByName("Label") if(info){ // 根据类型显示不同描述,目前天赋用desc let desc = ""; if (this.curCardType === CardType.Talent) { desc = data.desc || ""; } else if (this.curCardType === CardType.Skill) { desc = data.info || ""; } else if (this.curCardType === CardType.Partner) { desc = data.info || ""; } else { desc = data.desc || ""; } // 如果是物品,显示价格 if (this.curCardType === CardType.Potion && data.price) { desc += `\n价格: ${data.price}`; } info.getComponent(Label)!.string = desc; } } updateCardData(index: number, data: any) { // 使用动态属性访问,简化 switch 冗余代码 (this as any)[`card${index}_data`] = data; this.updateCardInfo((this as any)[`card${index}`], data); } selectCard(e: any, index: string) { console.log("selectCard", index) let _index = parseInt(index); // 如果已经选择过,则不再处理 if (this.hasSelected) return; // 动态获取数据和节点,简化 switch 逻辑 let selectedData: any = (this as any)[`card${_index}_data`]; let selectedCardNode: Node | null = (this as any)[`card${_index}`]; if (selectedData && selectedCardNode) { // 处理物品购买逻辑 if (this.curCardType === CardType.Potion) { if (this.purchasedSlots[_index]) { oops.gui.toast("该物品已购买"); return; } if (smc.vmdata.gold < selectedData.price) { oops.gui.toast("金币不足"); return; } // 扣除金币 smc.updateGold(-selectedData.price); // 发送使用物品事件 oops.message.dispatchEvent(GameEvent.UseItemCard, selectedData.id); // 标记已购买 this.purchasedSlots[_index] = true; // 视觉反馈 (变灰) const sprite = selectedCardNode.getComponent(Sprite); if (sprite) sprite.color = new Color(150, 150, 150); oops.gui.toast("购买成功"); // 检查是否所有卡片都已购买,如果是则关闭 let allPurchased = true; // 检查当前显示的卡片是否都买了 if (this.card1.active && !this.purchasedSlots[1]) allPurchased = false; if (this.card2.active && !this.purchasedSlots[2]) allPurchased = false; if (this.card3.active && !this.purchasedSlots[3]) allPurchased = false; if (this.card4.active && !this.purchasedSlots[4]) allPurchased = false; if (allPurchased) { this.close(); } return; } this.hasSelected = true; console.log("选择卡片:", selectedData.name, "类型:", this.curCardType); // 未选中的卡片缩小 const cards = [this.card1, this.card2, this.card3, this.card4]; cards.forEach(card => { if (card && card !== selectedCardNode) { tween(card).to(0.2, { scale: Vec3.ZERO }).start(); } }); // 显示当前选中的 selected 节点 const selected = selectedCardNode.getChildByName("selected"); if(selected) { selected.active = true; selected.setScale(Vec3.ZERO); tween(selected).to(0.2, { scale: new Vec3(1, 1, 1) }, { easing: 'backOut' }).start(); } // 选中卡片动效后触发逻辑 tween(selectedCardNode) .to(0.1, { scale: new Vec3(1.1, 1.1, 1.1) }) .to(0.1, { scale: new Vec3(1, 1, 1) }) .delay(0.5) .call(() => { // 根据类型发送不同事件 if (this.curCardType === CardType.Talent) { smc.addTalentRecord(selectedData.uuid); oops.message.dispatchEvent(GameEvent.UseTalentCard, selectedData.uuid); } else if (this.curCardType === CardType.Skill) { smc.addSkillRecord(selectedData.uuid); oops.message.dispatchEvent(GameEvent.UseSkillCard, selectedData.uuid); } else if (this.curCardType === CardType.Partner) { oops.message.dispatchEvent(GameEvent.CallFriend, { uuid: selectedData.uuid }); } // 后续扩展其他类型事件 this.close(); }) .start(); } } /** 看广告关闭 Lock */ watchAdCloseLock() { // TODO: 此处接入 IAA 广告 SDK console.log("播放激励视频广告..."); // 模拟广告播放成功回调 if (this.Lock) { this.Lock.active = false; oops.gui.toast("解锁成功"); } } /** * 关闭界面 */ close() { this.node.active = false; this.checkQueue(); } /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ reset() { this.node.destroy(); } }