refactor: 拆分技能卡配置到独立文件,优化抽卡逻辑
1. 新建SCardSet.ts单独管理技能卡池配置,将原CardSet.ts中的技能卡数据迁移 2. 重构多处业务代码,从SkillCardList而非CardPoolList获取技能卡配置 3. 简化技能卡抽卡逻辑,新增drawSkillCards工具函数统一处理抽卡 4. 修复TalentsComp中计算contentHeight的小语法问题 5. 新增技能卡商店显隐控制功能
This commit is contained in:
@@ -23,6 +23,7 @@ import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEven
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { CardConfig, CardType, SpecialRefreshCardList, SpecialUpgradeCardList, CKind, CardPoolList } from "../common/config/CardSet";
|
||||
import { SkillCardList } from "../common/config/SCardSet";
|
||||
import { CardBgComp } from "./CardBgComp";
|
||||
import { HeroInfo } from "../common/config/heroSet";
|
||||
import { SkillSet } from "../common/config/SkillSet";
|
||||
@@ -240,7 +241,7 @@ export class CardLiteComp extends CCComp {
|
||||
} else if (this.card_type === CardType.Skill) {
|
||||
if (this.lvl_node) this.lvl_node.node.active = false;
|
||||
const skill = SkillSet[this.card_uuid];
|
||||
const skillCard = CardPoolList.find(c => c.uuid === this.card_uuid);
|
||||
const skillCard = SkillCardList.find(c => c.uuid === this.card_uuid) ?? CardPoolList.find(c => c.uuid === this.card_uuid);
|
||||
const card_lv = Math.max(1, Math.floor(this.cardData.card_lv ?? 1));
|
||||
const spSuffix = card_lv >= 2 ? "★".repeat(card_lv - 1) : "";
|
||||
this.setLabel(this.name_node, `${spSuffix}${skillCard?.name || skill?.name || ""}${spSuffix}`);
|
||||
|
||||
@@ -36,6 +36,7 @@ import { MissionHeroComp } from "./MissionHeroComp";
|
||||
import { MoveComp } from "../hero/MoveComp";
|
||||
import { FacSet, getLvColor } from "../common/config/GameSet";
|
||||
import { CKind, CardPoolList, CardConfig, CardTriggerType } from "../common/config/CardSet";
|
||||
import { SkillCardList } from "../common/config/SCardSet";
|
||||
import { EquipPoolList } from "../common/config/EquipSet";
|
||||
import { SkillSet } from "../common/config/SkillSet";
|
||||
import { CardBgComp } from "./CardBgComp";
|
||||
@@ -188,7 +189,7 @@ export class HInfoComp extends CCComp {
|
||||
// 根据来源从对应卡池查询配置
|
||||
const config = this.isEquipCard
|
||||
? EquipPoolList.find(c => c.uuid === heroUuid)
|
||||
: CardPoolList.find(c => c.uuid === heroUuid);
|
||||
: (SkillCardList.find(c => c.uuid === heroUuid) ?? CardPoolList.find(c => c.uuid === heroUuid));
|
||||
if (!config) return;
|
||||
|
||||
if (this.nameLabel) this.nameLabel.string = config.name ?? "";
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, UITransform, Widget } 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 { CardConfig, CardType, CKind, CardPoolList } from "../common/config/CardSet";
|
||||
import { CardConfig, CardType, CKind } from "../common/config/CardSet";
|
||||
import { SkillCardList } from "../common/config/SCardSet";
|
||||
import { CardBgComp } from "./CardBgComp";
|
||||
import { FieldSkillSet, SkillSet } from "../common/config/SkillSet";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
@@ -104,7 +105,7 @@ export class SCardComp extends CCComp {
|
||||
smc.vmdata.scores.refresh_hit_count++;
|
||||
this.isUsing = true;
|
||||
const used = this.cardData;
|
||||
|
||||
|
||||
this.playUseDisappearAnim(() => {
|
||||
this.clearAfterUse();
|
||||
this.isUsing = false;
|
||||
@@ -255,7 +256,7 @@ export class SCardComp extends CCComp {
|
||||
|
||||
const s_uuid = this.cardData.skill ?? this.card_uuid;
|
||||
const skill = SkillSet[s_uuid];
|
||||
const skillCard = CardPoolList.find(c => c.uuid === this.card_uuid);
|
||||
const skillCard = SkillCardList.find(c => c.uuid === this.card_uuid);
|
||||
const card_lv = Math.max(1, Math.floor(this.cardData.card_lv ?? 1));
|
||||
const spSuffix = card_lv >= 2 ? "★".repeat(card_lv - 1) : "";
|
||||
this.setLabel(this.name_node, `${spSuffix}${skillCard?.name || skill?.name || ""}${spSuffix}`);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* - 销毁时通过 GameEvent.RemoveSkillBox 通知 MissSkillsComp 回收槽位
|
||||
*
|
||||
* 依赖:
|
||||
* - CardPoolList / CardTriggerType(CardSet)—— 查询技能卡的触发配置
|
||||
* - SkillCardList(SCardSet)/ CardTriggerType(CardSet)—— 查询技能卡的触发配置
|
||||
* - SkillSet —— 技能静态配置(icon 字段)
|
||||
* - GameEvent —— 各类游戏事件
|
||||
* - smc.mission —— 游戏运行状态
|
||||
@@ -33,7 +33,8 @@ import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Node, Prefab, Sprite, Label, Vec3, resources, SpriteAtlas, tween, v3, Tween, NodeEventType } 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 { CardPoolList, CardTriggerType } from "../common/config/CardSet";
|
||||
import { CardTriggerType } from "../common/config/CardSet";
|
||||
import { SkillCardList } from "../common/config/SCardSet";
|
||||
import { SkillSet, SkillOverrides, FieldSkillSet } from "../common/config/SkillSet";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
@@ -149,16 +150,16 @@ export class SkillBoxComp extends CCComp {
|
||||
if (!this.initialized) return;
|
||||
oops.audio.playEffect("music/button");
|
||||
// 点击时弹出 HInfoComp,传入卡牌 UUID 和等级以启用预览模式
|
||||
const config = CardPoolList.find(c => c.uuid === this.s_uuid || c.skill === this.s_uuid);
|
||||
const config = SkillCardList.find(c => c.uuid === this.s_uuid || c.skill === this.s_uuid);
|
||||
const cardUuid = config ? config.uuid : this.s_uuid;
|
||||
|
||||
|
||||
oops.gui.remove(UIID.HInfo);
|
||||
oops.gui.open(UIID.HInfo, { heroUuid: cardUuid, heroLv: this.card_lv, poolLv: config?.pool_lv ?? 1, isSkillCard: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化技能卡效果:
|
||||
* 1. 从 CardPoolList 查询技能卡的触发配置(含 trigger_type)。
|
||||
* 1. 从 SkillCardList 查询技能卡的触发配置(含 trigger_type)。
|
||||
* 2. 更新 UI 显示(图标 + 次数)。
|
||||
* 3. 按 trigger_type 注册对应事件监听并执行首次触发。
|
||||
*
|
||||
@@ -169,7 +170,7 @@ export class SkillBoxComp extends CCComp {
|
||||
this.card_lv = card_lv;
|
||||
|
||||
// 查询触发配置
|
||||
const config = CardPoolList.find(c => c.uuid === uuid);
|
||||
const config = SkillCardList.find(c => c.uuid === uuid);
|
||||
if (config) {
|
||||
this.s_uuid = config.skill ?? uuid; // 获取实际的技能 UUID
|
||||
this.is_instant = config.is_inst ?? true;
|
||||
|
||||
@@ -15,7 +15,8 @@ import { _decorator, instantiate, Node, Prefab, UITransform } 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 { mLogger } from "../common/Logger";
|
||||
import { CardPoolList, CardType, CardConfig } from "../common/config/CardSet";
|
||||
import { CardConfig } from "../common/config/CardSet";
|
||||
import { SkillCardList } from "../common/config/SCardSet";
|
||||
import { TalentItemComp } from "./TalentItemComp";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
@@ -51,7 +52,7 @@ export class TalentsComp extends CCComp {
|
||||
// 第一次:实例化所有子节点
|
||||
if (!this.rendered) {
|
||||
// 获取所有天赋(技能卡)并按 wave 和 uuid 排序
|
||||
this.cachedConfigs = CardPoolList.filter(card => card.type === CardType.Skill)
|
||||
this.cachedConfigs = [...SkillCardList]
|
||||
.sort((a, b) => {
|
||||
const waveA = a.wave || 1;
|
||||
const waveB = b.wave || 1;
|
||||
@@ -73,8 +74,8 @@ export class TalentsComp extends CCComp {
|
||||
// 默认底高 1000,每行 3 个天赋信息卡,每张卡高 270,行间距 15
|
||||
const totalCount = this.cachedConfigs.length;
|
||||
const rows = Math.ceil(totalCount / 3);
|
||||
const contentHeight = Math.max(1000, rows * 270 + (rows > 0 ? (rows - 1) * 15 : 0+50));
|
||||
|
||||
const contentHeight = Math.max(1000, rows * 270 + (rows > 0 ? (rows - 1) * 15 : 0 + 50));
|
||||
|
||||
const uiTransform = this.talents_content.getComponent(UITransform);
|
||||
if (uiTransform) {
|
||||
uiTransform.height = contentHeight;
|
||||
|
||||
Reference in New Issue
Block a user