- 新增 MissionCardComp 作为卡牌面板控制器,管理四个固定卡槽 - 实现抽卡按钮逻辑,根据卡池等级抽取并分发卡牌到四个槽位 - 实现卡池升级按钮,提升抽卡品质但不影响已锁定卡牌 - 新增 CardComp 作为单卡控制器,支持卡牌使用与槽位锁定功能 - 锁定状态下卡槽将跳过抽卡更新,保持原有卡牌 - 添加任务开始/结束时的卡槽清理与界面显隐控制 - 修复预制体字段缺失问题,补充 instance 和 targetOverrides 字段
155 lines
5.3 KiB
TypeScript
155 lines
5.3 KiB
TypeScript
import { mLogger } from "../common/Logger";
|
||
import { _decorator, Label, Node, NodeEventType, SpriteAtlas } 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 { GameEvent } from "../common/config/GameEvent";
|
||
import { CARD_POOL_INIT_LEVEL, CARD_POOL_MAX_LEVEL, CardConfig, getCardsByLv } from "../common/config/CardSet";
|
||
import { CardComp } from "./CardComp";
|
||
|
||
const { ccclass, property } = _decorator;
|
||
|
||
|
||
/** 视图层对象 */
|
||
@ccclass('MissionCardComp')
|
||
@ecs.register('MissionCard', false)
|
||
export class MissionCardComp extends CCComp {
|
||
private debugMode: boolean = true;
|
||
/** 四个插卡槽位(固定顺序分发:1~4) */
|
||
@property(Node)
|
||
card1:Node = null!
|
||
@property(Node)
|
||
card2:Node = null!
|
||
@property(Node)
|
||
card3:Node = null!
|
||
@property(Node)
|
||
card4:Node = null!
|
||
@property(Node)
|
||
cards_chou:Node = null!
|
||
@property(Node)
|
||
cards_up:Node = null!
|
||
|
||
/** 预留图集缓存(后续接入按钮/卡面图标时复用) */
|
||
private uiconsAtlas: SpriteAtlas | null = null;
|
||
/** 四个槽位对应的单卡控制器缓存 */
|
||
private cardComps: CardComp[] = [];
|
||
/** 当前卡池等级(仅影响抽卡来源,不直接改卡槽现有内容) */
|
||
private poolLv: number = CARD_POOL_INIT_LEVEL;
|
||
|
||
onLoad() {
|
||
/** 绑定事件 -> 缓存子控制器 -> 初始化UI状态 */
|
||
this.bindEvents();
|
||
this.cacheCardComps();
|
||
this.onMissionStart();
|
||
}
|
||
|
||
onDestroy() {
|
||
this.unbindEvents();
|
||
}
|
||
init(){
|
||
this.onMissionStart();
|
||
}
|
||
|
||
/** 任务开始时:重置卡池等级、清空4槽、显示面板 */
|
||
onMissionStart() {
|
||
this.poolLv = CARD_POOL_INIT_LEVEL;
|
||
this.clearAllCards();
|
||
this.updatePoolLvUI();
|
||
this.node.active = true;
|
||
}
|
||
|
||
/** 任务结束时:清空4槽并隐藏面板 */
|
||
onMissionEnd() {
|
||
this.clearAllCards();
|
||
this.node.active = false;
|
||
}
|
||
start() {
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/** 关闭面板(不销毁数据模型,仅隐藏) */
|
||
close() {
|
||
this.node.active = false;
|
||
}
|
||
|
||
/** 只处理UI层事件,不做卡牌效果分发 */
|
||
private bindEvents() {
|
||
/** 生命周期事件 */
|
||
this.on(GameEvent.MissionStart, this.onMissionStart, this);
|
||
this.on(GameEvent.MissionEnd, this.onMissionEnd, this);
|
||
/** 按钮事件:抽卡与卡池升级 */
|
||
this.cards_chou?.on(NodeEventType.TOUCH_END, this.onClickDraw, this);
|
||
this.cards_up?.on(NodeEventType.TOUCH_END, this.onClickUpgrade, this);
|
||
}
|
||
|
||
/** 解除按钮监听,避免节点销毁后回调泄漏 */
|
||
private unbindEvents() {
|
||
this.cards_chou?.off(NodeEventType.TOUCH_END, this.onClickDraw, this);
|
||
this.cards_up?.off(NodeEventType.TOUCH_END, this.onClickUpgrade, this);
|
||
}
|
||
|
||
/** 将四个卡槽节点映射为 CardComp,形成固定顺序控制数组 */
|
||
private cacheCardComps() {
|
||
const nodes = [this.card1, this.card2, this.card3, this.card4];
|
||
this.cardComps = nodes
|
||
.map(node => node?.getComponent(CardComp))
|
||
.filter((comp): comp is CardComp => !!comp);
|
||
}
|
||
|
||
/** 抽卡按钮:每次固定抽4张,然后顺序分发给4个单卡脚本 */
|
||
private onClickDraw() {
|
||
const cards = this.buildDrawCards();
|
||
this.dispatchCardsToSlots(cards);
|
||
}
|
||
|
||
/** 升级按钮:仅提升卡池等级,卡槽是否更新由下一次抽卡触发 */
|
||
private onClickUpgrade() {
|
||
if (this.poolLv >= CARD_POOL_MAX_LEVEL) return;
|
||
this.poolLv += 1;
|
||
this.updatePoolLvUI();
|
||
mLogger.log(this.debugMode, "MissionCardComp", "pool level up", this.poolLv);
|
||
}
|
||
|
||
/** 构建本次抽卡结果,保证最终可分发4条数据 */
|
||
private buildDrawCards(): CardConfig[] {
|
||
const cards = getCardsByLv(this.poolLv);
|
||
/** 正常情况下直接取前4 */
|
||
if (cards.length >= 4) return cards.slice(0, 4);
|
||
/** 兜底:当返回不足4张时循环补齐,保证分发不缺位 */
|
||
const filled = [...cards];
|
||
while (filled.length < 4) {
|
||
const fallback = getCardsByLv(this.poolLv);
|
||
if (fallback.length === 0) break;
|
||
filled.push(fallback[filled.length % fallback.length]);
|
||
}
|
||
return filled;
|
||
}
|
||
|
||
/** 全量分发给4槽;每个槽位是否接收由 CardComp 自己判断(锁定可跳过) */
|
||
private dispatchCardsToSlots(cards: CardConfig[]) {
|
||
for (let i = 0; i < this.cardComps.length; i++) {
|
||
this.cardComps[i].applyDrawCard(cards[i] ?? null);
|
||
}
|
||
}
|
||
|
||
/** 系统清空4槽(用于任务切换) */
|
||
private clearAllCards() {
|
||
this.cardComps.forEach(comp => comp.clearBySystem());
|
||
}
|
||
|
||
/** 更新升级按钮上的等级文案,反馈当前卡池层级 */
|
||
private updatePoolLvUI() {
|
||
if (!this.cards_up) return;
|
||
const label = this.cards_up.getComponentInChildren(Label);
|
||
if (!label) return;
|
||
label.string = `卡池Lv.${this.poolLv}`;
|
||
}
|
||
|
||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||
reset() {
|
||
this.node.destroy();
|
||
}
|
||
}
|