refactor: 统一将 pool_lv 重命名为 card_lv 并清理废弃代码

本次提交完成了全项目范围内的术语统一重构:
1.  将所有`pool_lv`相关变量、字段、注释替换为`card_lv`,对齐卡牌等级的业务含义
2.  移除了配置中冗余的默认`pool_lv`赋值,简化数据结构
3.  删除了废弃的`HlistComp.ts`组件及其元文件
4.  修正了多处逻辑错误,确保卡牌等级正确驱动背景框切换
5.  更新了相关注释和文档,保持代码一致性
This commit is contained in:
pan
2026-07-27 15:54:53 +08:00
parent 62264deeed
commit 9f2599e9ec
21 changed files with 137 additions and 467 deletions

View File

@@ -579,7 +579,7 @@ export class CHeroComp extends CCComp {
? (this.queryHeroUuidByEid(this.cardData.target_hero_eid as number) ?? this.cardData.uuid)
: this.cardData.uuid;
const heroLv = Math.max(1, this.cardData.hero_lv ?? 1);
const poolLv = Math.max(1, this.cardData.base_pool_lv ?? this.cardData.pool_lv ?? 1);
const poolLv = Math.max(1, this.cardData.base_card_lv ?? this.cardData.card_lv ?? 1);
// oops.gui 打开 HInfo 英雄卡预览
oops.gui.remove(UIID.HInfo);
@@ -612,7 +612,7 @@ export class CHeroComp extends CCComp {
reason: "",
uuid: this.cardData.uuid,
hero_lv: this.cardData.hero_lv ?? 1,
card_lv: this.cardData.base_pool_lv ?? this.cardData.pool_lv ?? 1
card_lv: this.cardData.base_card_lv ?? this.cardData.card_lv ?? 1
};
oops.message.dispatchEvent(GameEvent.UseHeroCard, guard);
if (guard.cancel) return;

View File

@@ -298,7 +298,7 @@ export class CardComp extends CCComp {
reason: "",
uuid: this.cardData.uuid,
hero_lv: this.cardData.hero_lv ?? 1,
card_lv: this.cardData.base_pool_lv ?? this.cardData.pool_lv ?? 1
card_lv: this.cardData.base_card_lv ?? this.cardData.card_lv ?? 1
};
oops.message.dispatchEvent(GameEvent.UseHeroCard, guard);
if (guard.cancel) {
@@ -549,7 +549,7 @@ export class CardComp extends CCComp {
? (this.queryHeroUuidByEid(this.cardData!.target_hero_eid as number) ?? this.card_uuid)
: this.card_uuid;
const heroLv = Math.max(1, this.cardData?.hero_lv ?? 1);
const poolLv = Math.max(1, this.cardData?.base_pool_lv ?? this.cardData?.pool_lv ?? 1);
const poolLv = Math.max(1, this.cardData?.base_card_lv ?? this.cardData?.card_lv ?? 1);
oops.gui.remove(UIID.HInfo);
oops.gui.open(UIID.HInfo, { heroUuid, heroLv, poolLv });
}
@@ -659,7 +659,7 @@ export class CardComp extends CCComp {
* 2. 技能卡:显示技能名(带品质后缀)、描述文本、静态图标。
* 3. 特殊卡:显示卡名(带品质后缀)、描述文本、静态图标。
*
* 同时根据 pool_lv 切换背景底框,根据 hero_lv / card_lv 切换普通/高级边框。
* 同时根据 card_lv 切换背景底框,根据 hero_lv / card_lv 切换普通/高级边框。
*/
private applyCardUI() {
if (!this.cardData) {
@@ -686,7 +686,7 @@ export class CardComp extends CCComp {
const kindName = CKind[renderKind];
if (this.BG_node) {
const bgLv = this.cardData.base_pool_lv ?? this.cardData.pool_lv;
const bgLv = this.cardData.base_card_lv ?? this.cardData.card_lv;
this.BG_node.children.forEach(child => {
child.active = (child.name === kindName);
const bg = child.getComponent(CardBgComp);

View File

@@ -115,10 +115,10 @@ export class CardLiteComp extends CCComp {
* 便捷方法:通过英雄 UUID 和卡池等级直接设置英雄卡。
* 自动从 CardPoolList 查找匹配的卡牌配置。
* @param uuid 英雄 UUID
* @param poolLv 卡等级(默认 1
* @param cardLv 卡等级(默认 1
*/
setHeroByUuid(uuid: number, poolLv: number = 1) {
const card = CardPoolList.find(c => c.uuid === uuid && c.pool_lv === poolLv);
setHeroByUuid(uuid: number, cardLv: number = 1) {
const card = CardPoolList.find(c => c.uuid === uuid && c.card_lv === cardLv);
if (card) {
this.setData(card);
return;
@@ -130,7 +130,7 @@ export class CardLiteComp extends CCComp {
type: CardType.Hero,
cost: 5,
weight: 25,
pool_lv: poolLv as any,
card_lv: cardLv,
kind: CKind.Hero,
hero_lv: hero.lv || 1
});
@@ -194,7 +194,7 @@ export class CardLiteComp extends CCComp {
* 2. 技能卡:显示技能名、静态图标。
* 3. 特殊卡:显示卡名、静态图标。
*
* 同时根据 pool_lv 切换背景底框,根据 kind 切换种类标识。
* 同时根据 card_lv 切换背景底框,根据 kind 切换种类标识。
*/
private applyCardUI() {
if (!this.cardData) {
@@ -221,7 +221,7 @@ export class CardLiteComp extends CCComp {
const kindName = CKind[this.cardData.kind];
if (this.BG_node) {
const bgLv = this.cardData.base_pool_lv ?? this.cardData.pool_lv;
const bgLv = this.cardData.base_card_lv ?? this.cardData.card_lv;
this.BG_node.children.forEach(child => {
child.active = (child.name === kindName);
const bg = child.getComponent(CardBgComp);

View File

@@ -333,7 +333,7 @@ export class HInfoComp extends CCComp {
this.BG_node.children.forEach(child => {
child.active = (child.name === kindName);
const bg = child.getComponent(CardBgComp);
if (bg) child.active ? bg.apply(this.model.base_pool_lv ?? this.model.pool_lv ?? 1) : bg.clear();
if (bg) child.active ? bg.apply(this.model.base_card_lv ?? this.model.card_lv ?? 1) : bg.clear();
});
}

View File

@@ -116,7 +116,7 @@ export class HerosListComp extends CCComp {
this.cards_node.removeAllChildren()
const sorted = [...HeroList].sort((a, b) => {
return (HeroInfo[a]?.pool_lv ?? 1) - (HeroInfo[b]?.pool_lv ?? 1);
return (HeroInfo[a]?.card_lv ?? 1) - (HeroInfo[b]?.card_lv ?? 1);
});
for (const uuid of sorted) {
@@ -136,7 +136,7 @@ export class HerosListComp extends CCComp {
})
const comp = cardNode.getComponent(CardLiteComp) || cardNode.addComponent(CardLiteComp)
comp.setHeroByUuid(uuid, hero.pool_lv ?? 1)
comp.setHeroByUuid(uuid, hero.card_lv ?? 1)
comp.onClickCallback = (cardComp: CardLiteComp) => {
this.onCardSelect(uuid)
this.highlightCard(cardNode)
@@ -209,7 +209,7 @@ export class HerosListComp extends CCComp {
if (infoLabel) infoLabel.string = desc || hero.info || ""
}
this.updatePoolLvBg(hero.pool_lv ?? 1)
this.updatePoolLvBg(hero.card_lv ?? 1)
this.updateLvDisplay(hero)
this.updateTypeDisplay(hero)
this.updateHeroAnimation(uuid)
@@ -237,7 +237,7 @@ export class HerosListComp extends CCComp {
private updateLvDisplay(hero: typeof HeroInfo[number]) {
if (!this.lv_node) return
const cardLvStr = `lv${hero.pool_lv ?? 1}`
const cardLvStr = `lv${hero.card_lv ?? 1}`
this.lv_node.active = true
this.lv_node.children.forEach(child => {

View File

@@ -1,330 +0,0 @@
/**
* @file HlistComp.ts
* @description 英雄列表轮播组件UI 视图层)
*
* 职责:
* 1. 在主页界面以 **5 格轮播** 形式展示英雄图鉴。
* 2. 支持左右切换,用 tween 动画平滑过渡节点位置。
* 3. 点击切换时自动更新当前选中英雄的名称、AP、HP 和技能信息。
*
* 关键设计:
* - carouselNodes[0..4] 对应 5 个展示位(最左-2 到最右+2
* 中间位 [2] 为当前选中英雄。
* - 切换时:将即将移出屏幕的节点瞬间跳转到另一端,再用 tween 滑入。
* - 切换完成后重排 carouselNodes 数组保持逻辑顺序。
* - iconVisualTokens 按节点独立管理竞态令牌,防止异步动画回调错乱。
*
* 依赖:
* - HeroInfo / HeroListheroSet—— 英雄静态配置与全量英雄 UUID 列表
* - SkillSet / ITypeSkillSet—— 技能配置与类型枚举
*/
import { _decorator, Animation, AnimationClip, Button, Event, Label, Node, NodeEventType, Sprite, resources, tween, Vec3, 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 { HeroInfo, HeroList } from "../common/config/heroSet";
import { IType, SkillSet } from "../common/config/SkillSet";
import { oops } from "db://oops-framework/core/Oops";
import { mLogger } from "../common/Logger";
import { UIID } from "../common/config/GameUIConfig";
const {property, ccclass } = _decorator;
/**
* HListComp —— 英雄图鉴轮播视图组件
*
* 在任务主页展示所有可用英雄,玩家可左右滑动查看:
* - 中间位显示完整信息(名称 / AP / HP / 技能列表)
* - 两侧位显示缩略 idle 动画
*/
@ccclass('HListComp')
@ecs.register('HListComp', false)
export class HListComp extends CCComp {
// ======================== 编辑器绑定节点 ========================
/** 中间位英雄 idle 图标节点 */
@property(Node)
hero_icon=null!
/** 攻击力标签节点 */
@property(Node)
ap_node=null!
/** 生命值标签节点 */
@property(Node)
hp_node=null!
/** 技能信息容器节点(包含 Line1~Line5 子节点) */
@property(Node)
info_node=null!
/** 英雄名称标签节点 */
@property(Node)
name_node=null!
/** 向左切换按钮 */
@property(Node)
lv_node=null!
// ======================== 运行时状态 ========================
/** 当前选中英雄在 HeroList 中的索引 */
huuid:number=null!
/** 当前选中英雄在 HeroList 数组中的下标 */
private currentIndex: number = 0;
/** 各图标节点的视觉令牌映射(防止异步动画竞态) */
private iconVisualTokens: Map<Node, number> = new Map();
/** 是否正在播放切换动画(防止快速连点) */
private isAnimating: boolean = false;
/** 轮播节点数组,顺序为 [左2, 左1, 中, 右1, 右2] */
private carouselNodes: Node[] = [];
/** 5 个固定位置坐标(从场景中读取初始值) */
private fixedPositions: Vec3[] = [];
/** 调试日志开关 */
debugMode: boolean = false;
onLoad() {
}
/** 预留:弹窗打开时接收参数 */
onAdded(args: any) {
}
/** 关闭排行榜弹窗 */
closeHeros(){
oops.gui.remove(UIID.Heros)
}
start() {
// 设置初始选中并加载所有位置的英雄动画
if (HeroList && HeroList.length > 0) {
this.currentIndex = 0;
this.initAllNodes();
this.updateHeroInfo();
}
}
// ======================== 切换逻辑 ========================
/**
* 向左切换(查看上一个英雄):
* 1. currentIndex 左移。
* 2. 最右节点 n4 瞬间跳到最左位置,加载新英雄动画。
* 3. 所有节点 tween 向右滑动一格。
* 4. 动画完成后重排 carouselNodes 数组。
*/
private onPreClick() {
if (!HeroList || HeroList.length === 0 || this.isAnimating || this.carouselNodes.length < 5) return;
this.isAnimating = true;
this.currentIndex = (this.currentIndex - 1 + HeroList.length) % HeroList.length;
const [n0, n1, n2, n3, n4] = this.carouselNodes;
// n4 瞬间跳至最左位置,准备滑入
n4.setPosition(new Vec3(this.fixedPositions[0].x, n4.position.y, n4.position.z));
this.updateNodeAnimationByOffset(n4, -2);
this.updateHeroInfo();
// 所有节点向右滑动一格
tween(n0).to(0.2, { position: new Vec3(this.fixedPositions[1].x, n0.position.y, n0.position.z) }).start();
tween(n1).to(0.2, { position: new Vec3(this.fixedPositions[2].x, n1.position.y, n1.position.z) }).start();
tween(n2).to(0.2, { position: new Vec3(this.fixedPositions[3].x, n2.position.y, n2.position.z) }).start();
tween(n3).to(0.2, { position: new Vec3(this.fixedPositions[4].x, n3.position.y, n3.position.z) })
.call(() => {
// 重排数组n4 成为新的最左节点
this.carouselNodes = [n4, n0, n1, n2, n3];
this.isAnimating = false;
})
.start();
}
/**
* 向右切换(查看下一个英雄):
* 1. currentIndex 右移。
* 2. 最左节点 n0 瞬间跳到最右位置,加载新英雄动画。
* 3. 所有节点 tween 向左滑动一格。
* 4. 动画完成后重排 carouselNodes 数组。
*/
private onNextClick() {
if (!HeroList || HeroList.length === 0 || this.isAnimating || this.carouselNodes.length < 5) return;
this.isAnimating = true;
this.currentIndex = (this.currentIndex + 1) % HeroList.length;
const [n0, n1, n2, n3, n4] = this.carouselNodes;
// n0 瞬间跳至最右位置,准备滑入
n0.setPosition(new Vec3(this.fixedPositions[4].x, n0.position.y, n0.position.z));
this.updateNodeAnimationByOffset(n0, 2);
this.updateHeroInfo();
// 所有节点向左滑动一格
tween(n1).to(0.2, { position: new Vec3(this.fixedPositions[0].x, n1.position.y, n1.position.z) }).start();
tween(n2).to(0.2, { position: new Vec3(this.fixedPositions[1].x, n2.position.y, n2.position.z) }).start();
tween(n3).to(0.2, { position: new Vec3(this.fixedPositions[2].x, n3.position.y, n3.position.z) }).start();
tween(n4).to(0.2, { position: new Vec3(this.fixedPositions[3].x, n4.position.y, n4.position.z) })
.call(() => {
// 重排数组n0 成为新的最右节点
this.carouselNodes = [n1, n2, n3, n4, n0];
this.isAnimating = false;
})
.start();
}
// ======================== 数据查询 ========================
/**
* 根据偏移量获取英雄 UUID。
* @param offset 相对于当前选中英雄的偏移(-2, -1, 0, 1, 2
* @returns HeroList 中对应位置的英雄 UUID
*/
private getHeroUuid(offset: number): number {
const len = HeroList.length;
return HeroList[(this.currentIndex + offset + len * 5) % len];
}
/**
* 按偏移量更新指定节点的英雄动画。
* @param node 目标图标节点
* @param offset 偏移量
*/
private updateNodeAnimationByOffset(node: Node, offset: number) {
const uuid = this.getHeroUuid(offset);
this.updateHeroAnimation(node, uuid);
}
/** 更新当前选中英雄的详细信息名称、AP、HP、技能列表 */
private updateHeroInfo() {
this.huuid = this.getHeroUuid(0);
const hero = HeroInfo[this.huuid];
if (!hero) return;
const heroLv = Math.max(1, Math.floor(hero.lv ?? 1));
const suffix = heroLv >= 2 ? "★".repeat(heroLv - 1) : "";
this.setLabelText(this.name_node, `${suffix}${hero.name || ""}${suffix}`);
this.setLabelText(this.ap_node, `${(hero.ap ?? 0) * heroLv}`);
this.setLabelText(this.hp_node, `${(hero.hp ?? 0) * heroLv}`);
if (this.info_node) {
const infoLabel = this.info_node.getChildByName("info")?.getComponent(Label);
if (infoLabel) infoLabel.string = `${hero.info || ""}`;
}
const cardLvStr = `lv${hero.pool_lv ?? 1}`;
if (this.lv_node) {
this.lv_node.active = true;
this.lv_node.children.forEach(child => {
if (child.name === "light") {
child.active = false;
} else if (child.name === "bg") {
child.active = true;
} else {
child.active = (child.name === cardLvStr);
}
});
const widget = this.lv_node.getComponent(Widget);
if (widget) widget.updateAlignment();
this.lv_node.children.forEach(child => {
const childWidget = child.getComponent(Widget);
if (childWidget) childWidget.updateAlignment();
});
}
}
/** 初始化 5 个轮播位的英雄动画 */
private initAllNodes() {
if (this.carouselNodes.length < 5) return;
this.updateNodeAnimationByOffset(this.carouselNodes[0], -2);
this.updateNodeAnimationByOffset(this.carouselNodes[1], -1);
this.updateNodeAnimationByOffset(this.carouselNodes[2], 0);
this.updateNodeAnimationByOffset(this.carouselNodes[3], 1);
this.updateNodeAnimationByOffset(this.carouselNodes[4], 2);
}
// ======================== UI 工具 ========================
/**
* 安全设置 Label 文本
* @param node 标签所在节点
* @param text 文本内容
*/
private setLabelText(node: Node, text: string) {
if (!node) return;
const label = node.getComponent(Label) || node.getComponentInChildren(Label);
if (label) {
label.string = text;
}
}
// ======================== 英雄动画 ========================
/**
* 为指定节点加载并播放英雄 idle 动画。
* 使用 iconVisualTokens 做节点级竞态保护。
*
* @param node 图标节点
* @param uuid 英雄 UUID
*/
private updateHeroAnimation(node: Node, uuid: number) {
if (!node) return;
const sprite = node.getComponent(Sprite) || node.getComponentInChildren(Sprite);
if (sprite) sprite.spriteFrame = null;
const hero = HeroInfo[uuid];
if (!hero) return;
const anim = node.getComponent(Animation) || node.addComponent(Animation);
this.clearAnimationClips(anim);
// 递增该节点的视觉令牌
let token = (this.iconVisualTokens.get(node) || 0) + 1;
this.iconVisualTokens.set(node, token);
const path = `game/heros/hero/${hero.path}/idle`;
resources.load(path, AnimationClip, (err, clip) => {
if (err || !clip) {
mLogger.log(this.debugMode, "HListComp", `load hero animation failed ${uuid}`, err);
return;
}
// 竞态保护:令牌不匹配则丢弃
if (token !== this.iconVisualTokens.get(node)) {
return;
}
this.clearAnimationClips(anim);
anim.addClip(clip);
anim.play("idle");
});
}
/** 移除 Animation 上的全部 clip倒序遍历避免索引偏移 */
private clearAnimationClips(anim: Animation) {
const clips = anim.clips;
if (clips && clips.length > 0) {
for (let i = clips.length - 1; i >= 0; i--) {
const clip = clips[i];
if (clip) anim.removeClip(clip, true);
}
}
}
/**
* 递归查找子节点(按名称)
* @param root 起始节点
* @param name 目标节点名
*/
private findNodeByName(root: Node, name: string): Node | null {
if (!root) return null;
if (root.name === name) return root;
for (let i = 0; i < root.children.length; i++) {
const res = this.findNodeByName(root.children[i], name);
if (res) return res;
}
return null;
}
/** ECS 组件移除时销毁节点 */
reset() {
this.node.destroy();
}
}

View File

@@ -1 +0,0 @@
{"ver":"4.0.24","importer":"typescript","imported":true,"uuid":"89bf6d65-5432-4946-9b14-3e5150dddedd","files":[],"subMetas":{},"userData":{}}

View File

@@ -419,7 +419,7 @@ export class ItemListComp extends CCComp {
oops.gui.open(UIID.HInfo, {
heroUuid: cardUuid,
heroLv: this.cardData.card_lv ?? 1,
poolLv: config?.pool_lv ?? 1,
poolLv: config?.card_lv ?? 1,
isSkillCard: true
});
}

View File

@@ -73,7 +73,7 @@ export class MissionHeroComp extends CCComp {
/** 是否正在消费召唤队列(防止并发) */
is_processing_queue: boolean = false
/** 召唤请求队列:保证召唤按顺序串行执行 */
summon_queue: { uuid: number; hero_lv: number; pool_lv: number }[] = []
summon_queue: { uuid: number; hero_lv: number; card_lv: number }[] = []
/** 预留英雄列表 */
heros: any = []
@@ -141,17 +141,17 @@ export class MissionHeroComp extends CCComp {
/**
* 召唤请求入口:
* 从事件参数中提取 uuid / hero_lv / pool_lv放入串行队列。
* 从事件参数中提取 uuid / hero_lv / card_lv放入串行队列。
* 防御:已召唤的英雄 uuid 拒绝重复召唤(只能通过升级卡升级)。
*
* @param event 事件名
* @param args { uuid, hero_lv, pool_lv }
* @param args { uuid, hero_lv, card_lv }
*/
private async call_hero(event: string, args: any) {
const payload = args ?? event;
const uuid = Number(payload?.uuid ?? 1001);
const hero_lv = Math.max(1, Number(payload?.hero_lv ?? 1));
const pool_lv = Math.max(1, Number(payload?.pool_lv ?? 1));
const card_lv = Math.max(1, Number(payload?.card_lv ?? 1));
// 防御:场上已有同 uuid 的存活英雄时,拒绝重复召唤
if (this.isHeroAlreadySummoned(uuid)) {
@@ -159,7 +159,7 @@ export class MissionHeroComp extends CCComp {
return;
}
this.summon_queue.push({ uuid, hero_lv, pool_lv });
this.summon_queue.push({ uuid, hero_lv, card_lv });
this.processSummonQueue();
}
@@ -216,16 +216,16 @@ export class MissionHeroComp extends CCComp {
*
* @param uuid 英雄 UUID
* @param hero_lv 英雄等级
* @param pool_lv 卡等级(历史遗留,新机制下不再使用
* @param card_lv 卡等级(驱动 bg_node 颜色
* @returns 创建的 Hero 实体
*/
private addHero(uuid: number = 1001, hero_lv: number = 1, pool_lv: number = 1) {
private addHero(uuid: number = 1001, hero_lv: number = 1, card_lv: number = 1) {
let hero = ecs.getEntity<Hero>(Hero);
let scale = 1
const posIndex = this.pickPositionIndexForHero();
const landingPos = MissionHeroComp.HERO_POSITIONS[posIndex];
let spawnPos: Vec3 = v3(landingPos.x, landingPos.y + MissionHeroComp.HERO_DROP_HEIGHT, 0);
hero.load(spawnPos, scale, uuid, landingPos.y, hero_lv, pool_lv, posIndex);
hero.load(spawnPos, scale, uuid, landingPos.y, hero_lv, card_lv, posIndex);
// 召唤完成后,派发事件以更新英雄面板
const model = hero.get(HeroAttrsComp);
@@ -267,7 +267,7 @@ export class MissionHeroComp extends CCComp {
while (this.summon_queue.length > 0) {
const payload = this.summon_queue.shift();
if (!payload) continue;
await this.handleSingleSummon(payload.uuid, payload.hero_lv, payload.pool_lv);
await this.handleSingleSummon(payload.uuid, payload.hero_lv, payload.card_lv);
}
} finally {
this.is_processing_queue = false;
@@ -279,10 +279,10 @@ export class MissionHeroComp extends CCComp {
*
* @param uuid 英雄 UUID
* @param hero_lv 英雄等级
* @param pool_lv 卡等级(历史遗留)
* @param card_lv 卡等级
*/
private async handleSingleSummon(uuid: number, hero_lv: number, pool_lv: number = 1) {
this.addHero(uuid, hero_lv, pool_lv);
private async handleSingleSummon(uuid: number, hero_lv: number, card_lv: number = 1) {
this.addHero(uuid, hero_lv, card_lv);
}

View File

@@ -409,7 +409,7 @@ export class SCardComp extends CCComp {
oops.gui.open(UIID.HInfo, {
heroUuid: cardUuid,
heroLv: this.cardData.card_lv ?? 1,
poolLv: config?.pool_lv ?? 1,
poolLv: config?.card_lv ?? 1,
isSkillCard: true
});
}

View File

@@ -186,7 +186,7 @@ export class SkillBoxComp extends CCComp {
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 });
oops.gui.open(UIID.HInfo, { heroUuid: cardUuid, heroLv: this.card_lv, poolLv: config?.card_lv ?? 1, isSkillCard: true });
}
/**

View File

@@ -49,10 +49,10 @@ export class TalentItemComp extends CCComp {
if (this.lbl_name) this.lbl_name.string = config.name ?? "";
if (this.lbl_info) this.lbl_info.string = config.info ?? "";
// 直接复用 CardSet 中已映射好的 pool_lv保证与技能卡牌背景一致
// CardSet 通过 waveToPoolLv[wave] 由 SKILL_CARD_WAVES 索引推导wave 1→1, 5→2, 8→3
// 直接复用 CardSet 中已映射好的 card_lv保证与技能卡牌背景一致
// CardSet 通过 waveToCardLv[wave] 由 SKILL_CARD_WAVES 索引推导wave 1→1, 5→2, 8→3
if (this.bg) {
this.bg.apply(config.pool_lv || 1);
this.bg.apply(config.card_lv || 1);
}
// 设置图标:驻场卡(skill=undefined 但有 field)走 FieldSkillSet否则走 SkillSet

View File

@@ -172,9 +172,9 @@ export class VictoryComp extends CCComp {
cost: 0,
weight: 0,
kind: CKind.Hero,
pool_lv: mvp.pool_lv || CardLV.LV1,
card_lv: mvp.card_lv || 1,
hero_lv: mvp.lv || 1,
base_pool_lv: mvp.base_pool_lv || mvp.pool_lv || 1,
base_card_lv: mvp.base_card_lv || mvp.card_lv || 1,
};
const originalPos = this.mvp_node.position.clone();