refactor: 拆分技能卡配置到独立文件,优化抽卡逻辑

1. 新建SCardSet.ts单独管理技能卡池配置,将原CardSet.ts中的技能卡数据迁移
2. 重构多处业务代码,从SkillCardList而非CardPoolList获取技能卡配置
3. 简化技能卡抽卡逻辑,新增drawSkillCards工具函数统一处理抽卡
4. 修复TalentsComp中计算contentHeight的小语法问题
5. 新增技能卡商店显隐控制功能
This commit is contained in:
pan
2026-07-22 17:42:41 +08:00
parent c10781a180
commit 30163e8dac
10 changed files with 8201 additions and 989 deletions

View File

@@ -40,6 +40,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { GameEvent } from "../common/config/GameEvent";
import { CardConfig, CardPoolList, CardType, drawCardsByRule, SpecialRefreshCardList, SpecialRefreshHeroType, SpecialUpgradeCardList } from "../common/config/CardSet";
import { drawSkillCards } from "../common/config/SCardSet";
import { EquipPoolList } from "../common/config/EquipSet";
import { CardComp } from "./CardComp";
import { SCardComp } from "./SCardComp";
@@ -229,6 +230,12 @@ export class MissionCardComp extends CCComp {
if (this.closeEquips && this.closeEquips.isValid) {
this.closeEquips.off(NodeEventType.TOUCH_END, this.onCloseEquipsClick, this);
}
if (this.showSkills && this.showSkills.isValid) {
this.showSkills.off(NodeEventType.TOUCH_END, this.onShowSkillsClick, this);
}
if (this.closeSkills && this.closeSkills.isValid) {
this.closeSkills.off(NodeEventType.TOUCH_END, this.onCloseSkillsClick, this);
}
this.unbindEvents();
}
@@ -275,6 +282,9 @@ export class MissionCardComp extends CCComp {
this.purchasedEquipUuids.clear();
this.populateEquipments();
// 首次进入准备阶段自动抽取一次技能卡,后续刷新只能通过技能刷新按钮触发
this.initSkillCardsOnce();
mLogger.log(this.debugMode, "MissionCardComp", "mission start");
}
@@ -346,6 +356,11 @@ export class MissionCardComp extends CCComp {
/** 关闭装备商店按钮 */
this.closeEquips?.on(NodeEventType.TOUCH_END, this.onCloseEquipsClick, this);
/** 技能卡池显示按钮 */
this.showSkills?.on(NodeEventType.TOUCH_END, this.onShowSkillsClick, this);
/** 关闭技能卡池按钮 */
this.closeSkills?.on(NodeEventType.TOUCH_END, this.onCloseSkillsClick, this);
/** 技能卡刷新按钮 */
this.skill_refresh?.on(NodeEventType.TOUCH_START, this.onSkillDrawTouchStart, this);
this.skill_refresh?.on(NodeEventType.TOUCH_END, this.onSkillDrawTouchEnd, this);
@@ -455,10 +470,19 @@ export class MissionCardComp extends CCComp {
}
}
private showSkillCardPopup() {
if (!this.skill_card_node) return;
this.skill_card_node.active = true;
// 先分发卡牌数据(让卡面内容就绪),再做入场动画
/**
* 首次进入准备阶段时自动抽取一次技能卡:
* - 仅在任务开始时调用一次。
* - 后续抽卡只能通过技能刷新按钮触发。
*/
private initSkillCardsOnce() {
if (this.skillCardComps.length === 0) {
this.cacheCardComps();
}
// 显示技能卡牌面板
if (this.skill_card_node) {
this.skill_card_node.active = true;
}
const cards = this.buildSkillDrawCards();
this.dispatchCardsToSkillSlots(cards);
this.playSkillCardEnterAnim();
@@ -469,6 +493,25 @@ export class MissionCardComp extends CCComp {
}
}
/**
* 技能卡池显隐切换按钮回调:
* - 仅切换 skill_card_node 的 active 状态,不执行抽卡。
* - 后续刷新需通过技能刷新按钮skill_refresh触发。
*/
private onShowSkillsClick() {
if (!this.skill_card_node || !this.skill_card_node.isValid) return;
oops.audio.playEffect("music/button");
const visible = !this.skill_card_node.active;
this.skill_card_node.active = visible;
}
/** 关闭技能卡池按钮回调 */
private onCloseSkillsClick() {
if (!this.skill_card_node || !this.skill_card_node.isValid) return;
oops.audio.playEffect("music/button");
this.skill_card_node.active = false;
}
private dispatchCardsToSkillSlots(cards: CardConfig[]) {
if (!this.skillCardComps) return;
for (let i = 0; i < this.skillCardComps.length; i++) {
@@ -1088,36 +1131,14 @@ export class MissionCardComp extends CCComp {
return result;
}
/**
* 构建技能卡抽卡结果,返回 3 张。
*
* 技能卡池长期存在,不再按波次过滤,
* 直接从 SCardSet 的 drawSkillCards 按权重抽取。
*/
private buildSkillDrawCards(): CardConfig[] {
const currentWave = this.getCurrentWave();
// 使用明确规则的 drawCardsByRule指定只要 3 张技能卡,并且过滤对应 wave
const cards = drawCardsByRule(1, {
count: 3,
type: CardType.Skill,
wave: currentWave,
unique: true, // 保证技能牌不重复
});
if (cards.length >= 3) return cards.slice(0, 3);
const filled = [...cards];
while (filled.length < 3) {
const fallback = drawCardsByRule(1, {
count: 3,
type: CardType.Skill,
wave: currentWave,
unique: true,
});
if (fallback.length === 0) break;
// 如果池子数量不足,只能被迫允许重复,但尽量拿没被抽到的
const fPick = fallback.find(c => !filled.some(fc => fc.uuid === c.uuid));
if (fPick) {
filled.push(fPick);
} else {
filled.push(fallback[filled.length % fallback.length]);
}
}
return filled;
return drawSkillCards(3);
}
private tryRefreshHeroCards(heroType?: HType): boolean {
@@ -1427,11 +1448,6 @@ export class MissionCardComp extends CCComp {
return Math.max(0, Math.floor(missionData?.hero_num ?? 0));
}
private getCurrentWave(): number {
const missionData = this.getMissionData();
return Math.max(1, Math.floor(missionData?.level ?? 1));
}
private getMissionHeroMaxNum(): number {
return FightSet.HERO_MAX_NUM
}