4 Commits

Author SHA1 Message Date
panFD
cfaed3b63f docs(rich-text): 新增富文本描边规范文档
替换原有的SkillSet/heroSet配置规则文档,新增Cocos Creator富文本描边使用规范,包含使用示例和注意事项。同时重构英雄列表组件,添加升级属性提升说明的富文本展示功能,使用统一的描边工具类美化文本显示。
2026-09-08 21:40:34 +08:00
panFD
57a50578fa style(ui): 优化天赋道具项UI表现与逻辑
1. 移除未激活天赋的灰阶处理,仅保留锁遮罩
2. 重构applyTierBg方法,移除背景灰阶逻辑
3. 调整天赋预制体的尺寸、缩放、文本样式与图标资源
2026-09-08 20:46:23 +08:00
panFD
07f1646013 feat(skillBox): add hero level unlock prompt for locked skills
1. 新增unlock_lv字段存储技能解锁所需英雄等级,与技能等级解耦
2. 优化锁定状态下的UI展示:优先显示等级解锁提示,回退使用技能等级
3. 重构技能图标生成逻辑,传递解锁等级参数
4. 更新天赋道具预制体,适配新的解锁提示UI展示逻辑
2026-09-08 20:04:27 +08:00
panFD
056feba945 refactor(sibox): 重构英雄头像盒子预制体
1.  删除冗余的herobox.prefab.meta文件
2.  重新组织sibox的节点结构与组件配置
3.  更新精灵帧与材质引用,调整节点缩放与布局参数
4.  优化激活状态与子节点管理逻辑
2026-09-08 19:51:21 +08:00
13 changed files with 9529 additions and 16587 deletions

View File

@@ -60,90 +60,29 @@ alwaysApply: true
--- ---
# SkillSet / heroSet 配置规则 # RichText 描边规范
## 核心原则 ## 背景
1. **技能底座纯净化**:SkillSet 中的技能只定义基础行为(伤害、弹道、命中),**禁止**在基础配置中写死 `timed_buff_id` / `buff_type` 等效果字段 Cocos Creator 3.x 的 `cc.RichText` 原生支持 `<outline>` 标签,无需新增组件即可为富文本提供描边能力。
2. **效果由引用处注入**:英雄/怪物引用技能时,通过 `HSkillInfo.overrides` 按需附加 debuff/buff,实现"同一技能、不同效果"
3. **数值覆盖优先**:`ap`(伤害百分比)、`hit_count`、`crt` 等数值差异,统一由 `overrides` 覆写,而非新建相似技能
4. **Buff 统一百分比口径**:无论永久 buff(`buff_type`)还是计时 buff(`timed_buff_id`),修饰数值均按百分比/百分点结算;`ap`/`hp_max` 按基础值相对放大,概率类属性按百分点累加
## SkillSet 配置规范 ## 使用方式
### 技能 uuid 段位分配
| 段位 | 用途 | 示例 |
|------|------|------|
| 6001-6099 | 基础单体攻击(近战/远程通用底座) | 6001 飞剑、6004 攻击 |
| 6100-6199 | 中阶攻击技能(高阶特效/多命中) | 6101 火球、6102 飓风 |
| 6200-6299 | 高阶范围技能(AOE/必杀) | 6201 陨石术 |
| 6300-6399 | 辅助/治疗/护盾技能 | 6301 护盾、6302 治疗 |
| 6400-6499 | 永久属性强化(buff_type) | 6401 攻击强化 |
| 6500-6599 | 计时爆发技能(timed_buff_id) | 6501 复活 |
### 新增技能检查清单
- [ ] uuid 在对应段位内,且未与现有技能冲突
- [ ] `sp_name` / `icon` 与现有技能不重复(避免视觉混淆)
- [ ] `IType`(近战/远程/辅助)与 `RType`(弹道类型)匹配合理
- [ ] 基础配置**不含** `timed_buff_id` / `buff_type`(效果由引用处注入)
- [ ] `info` 描述只写基础效果,不写具体 debuff(如"造成攻击力100%的伤害")
## heroSet 配置规范
### 英雄 uuid 段位分配
| 段位 | 品质 | 说明 |
|------|------|------|
| 5001-5099 | card_lv=1 | 基础单体/默认范围 |
| 5101-5199 | card_lv=2 | 数值强化 |
| 5201-5299 | card_lv=3 | 范围扩大 |
| 5301-5399 | card_lv=4 | 数值+范围 |
| 5401-5499 | card_lv=5 | 双技能(+revive/field) |
### 怪物 uuid 段位分配
| 段位 | 类型 |
|------|------|
| 6001-6099 | 基础怪物(近战/远程/特殊位) |
| 6100-6199 | Boss 怪物 |
### 新增英雄/怪物检查清单
- [ ] `skills` 引用的技能 uuid 在 SkillSet 中存在
- [ ] 技能效果通过 `overrides` 按需注入,**禁止**直接修改 SkillSet 基础配置
- [ ] `overrides.ap` 明确写出(如 80/100/150),避免依赖基础配置的默认值
- [ ] `timed_buff_id` 指向 BuffList 中存在的 buff 配置
- [ ] 怪物技能引用优先使用 6001-6012 基础技能,Boss 可用 6101+ 中阶技能
### 触发技能配置规则
| 触发类型 | 字段 | 说明 |
|----------|------|------|
| 普通攻击 | `skills` | 携带技能,`overrides` 注入效果 |
| 受击触发 | `atked` | 按 s_uuid 分组,按 lv 升序 |
| 攻击后触发 | `atking` | 按 s_uuid 分组,按 lv 升序 |
| 死亡触发 | `dead` | 按 s_uuid 分组,按 lv 升序 |
| 战斗开始 | `fstart` | 按 s_uuid 分组,按 lv 升序 |
| 驻场光环 | `field` | `FieldEntry[]`,按 lv 升序 |
| 复活 | `revive` | `LvReviveEntry[]`,按 lv 升序 |
### 示例:同一技能不同效果
```typescript ```typescript
// SkillSet 6101 火球 — 纯伤害底座,无 debuff import { outlineRich } from "../common/RichOutline";
6101: {
uuid: 6101, name: "火球", sp_name: "fb-1", ...,
// 禁止写 timed_buff_id / buff_type
}
// heroSet 5004 破晓先知 — 冰冻版火球 // 默认黑色 2px 描边
skills: { 6101: { uuid: 6101, overrides: { ap: 80, timed_buff_id: 7003 } } } this.info_rich.string = outlineRich(desc);
// heroSet 5304 战吼术士 — 中毒版火球 // 自定义颜色与宽度
skills: { 6101: { uuid: 6101, overrides: { ap: 80, timed_buff_id: 7005 } } } this.info_rich.string = outlineRich(desc, "#000", 1);
// heroSet 6008 兽人火法 — 原版火球(ap=100,无 debuff)
skills: { 6101: { uuid: 6101 } }
``` ```
## 注意事项
- `<outline>` 为包裹型标签,需成对出现;内部可嵌套 `<color>`/`<size>` 等标签
- `width` 为像素宽度(int),`color` 支持 `#RGB`/`#RRGGBB`
- 空字符串直接返回,不包裹空标签
---

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "f820a186-b9f6-44df-a534-bdcbaa6a639a",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "herobox"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 KiB

After

Width:  |  Height:  |  Size: 973 KiB

View File

@@ -17,13 +17,14 @@
* - CardLiteComp —— 轻量卡片组件 * - CardLiteComp —— 轻量卡片组件
* - buildHeroSkillDesc(HeroSkillText)—— 技能描述生成器(局外等级口径) * - buildHeroSkillDesc(HeroSkillText)—— 技能描述生成器(局外等级口径)
*/ */
import { _decorator, Animation, AnimationClip, Button, Label, Node, Prefab, Sprite, UITransform, Vec3, Widget, instantiate, resources, tween, Tween } from "cc"; import { _decorator, Animation, AnimationClip, Button, Label, Node, Prefab, RichText, Sprite, UITransform, Vec3, Widget, instantiate, resources, tween, Tween } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { oops } from "db://oops-framework/core/Oops"; import { oops } from "db://oops-framework/core/Oops";
import { mLogger } from "../common/Logger"; import { mLogger } from "../common/Logger";
import { HeroInfo, HeroList, SkillTriggerType, LvFieldEntry, LvTriggerEntry, TriggerGrouped, HSkillInfo, getHeroDisplayStats, LvBonusAttrsEntry } from "../common/config/heroSet"; import { HeroInfo, HeroList, SkillTriggerType, LvFieldEntry, LvTriggerEntry, TriggerGrouped, HSkillInfo, getHeroDisplayStats, LvBonusAttrsEntry } from "../common/config/heroSet";
import { buildHeroSkillDesc } from "../common/HeroSkillText"; import { buildHeroSkillDesc } from "../common/HeroSkillText";
import { outlineRich } from "../common/RichOutline";
import { GameEvent } from "../common/config/GameEvent"; import { GameEvent } from "../common/config/GameEvent";
import { HERO_UPGRADE_NEED_FRAGMENTS, RARITY_BG_COLORS } from "../common/config/GameSet"; import { HERO_UPGRADE_NEED_FRAGMENTS, RARITY_BG_COLORS } from "../common/config/GameSet";
import { CardLiteComp } from "./CardLiteComp"; import { CardLiteComp } from "./CardLiteComp";
@@ -105,6 +106,14 @@ export class HerosListComp extends CCComp {
@property(Node) @property(Node)
upgrade_anim_node = null! upgrade_anim_node = null!
/** 碎片需求/总量 Label(显示 当前碎片 / 下级需求) */
@property(Label)
fragment_label = null!
/** 升级提升加成说明 RichText(展示升级后的属性提升,数值绿色高亮) */
@property(RichText)
upgrade_info_label = null!
// ======================== 运行时状态 ======================== // ======================== 运行时状态 ========================
huuid: number = 0 huuid: number = 0
@@ -470,6 +479,16 @@ export class HerosListComp extends CCComp {
: `${growth.fragments} / ${needFragments}` : `${growth.fragments} / ${needFragments}`
this.setLabelText(this.fragment_node, fragmentText) this.setLabelText(this.fragment_node, fragmentText)
} }
// 独立碎片 Label(编辑器可直接绑定 Label 组件,与 fragment_node 二选一或并存)
if (this.fragment_label) {
const fragmentText = isMaxLv
? `${growth.fragments} / MAX`
: `${growth.fragments} / ${needFragments}`
this.fragment_label.string = fragmentText
}
// 升级提升加成说明
this.updateUpgradeInfoLabel(uuid, growth.lv, isMaxLv)
// 碎片图标:使用 ChipComp 渲染英雄图标(自动读取 HeroInfo 配置) // 碎片图标:使用 ChipComp 渲染英雄图标(自动读取 HeroInfo 配置)
if (this.chip_node) { if (this.chip_node) {
@@ -488,6 +507,39 @@ export class HerosListComp extends CCComp {
// ======================== 技能图标列表 ======================== // ======================== 技能图标列表 ========================
/**
* 刷新升级提升加成说明 RichText
* 展示口径:对比当前等级与下一等级,仅列出 AP/HP/DEF 属性差值,单行展示
* 数值用绿色高亮,整体通过 outlineRich 包裹描边标签
* @param uuid 英雄模板 uuid
* @param curLv 当前局外等级(≥1)
* @param isMaxLv 是否已满级
*/
private updateUpgradeInfoLabel(uuid: number, curLv: number, isMaxLv: boolean) {
if (!this.upgrade_info_label) return
const hero = HeroInfo[uuid]
if (!hero) { this.upgrade_info_label.string = ""; return }
if (isMaxLv) {
this.upgrade_info_label.string = outlineRich("已满级")
return
}
const nextLv = curLv + 1
const cur = getHeroDisplayStats(hero, curLv)
const nxt = getHeroDisplayStats(hero, nextLv)
// 属性提升差值:单行展示 AP/HP/DEF,数值绿色高亮
const parts: string[] = []
if (nxt.hp > cur.hp) parts.push(`生命<color=#00FF00>+${nxt.hp - cur.hp}</color>`)
if (nxt.ap > cur.ap) parts.push(`攻击<color=#00FF00>+${nxt.ap - cur.ap}</color>`)
if (nxt.def > cur.def) parts.push(`防御<color=#00FF00>+${nxt.def - cur.def}</color>`)
this.upgrade_info_label.string = parts.length > 0
? outlineRich(`升级属性提升:${parts.join(" ")}`)
: outlineRich(`升级至 Lv.${nextLv}`)
}
/** 图鉴面板展示的触发技能槽位(按触发时机排序:召唤→战斗开始→攻击后→受击后→死亡→常驻光环) */ /** 图鉴面板展示的触发技能槽位(按触发时机排序:召唤→战斗开始→攻击后→受击后→死亡→常驻光环) */
private static readonly PANEL_TRIGGER_TYPES: SkillTriggerType[] = [ private static readonly PANEL_TRIGGER_TYPES: SkillTriggerType[] = [
SkillTriggerType.Call, SkillTriggerType.Call,
@@ -571,13 +623,14 @@ export class HerosListComp extends CCComp {
* 弹窗按整组合并渲染(组内多技能/词条统一说明) * 弹窗按整组合并渲染(组内多技能/词条统一说明)
* @param normalLv2 普攻 lv2 专属模式:该图标代表普攻 lv2 强化档,名称/图标取 lv1, * @param normalLv2 普攻 lv2 专属模式:该图标代表普攻 lv2 强化档,名称/图标取 lv1,
* 弹窗只展示 lv2 档位说明 * 弹窗只展示 lv2 档位说明
* @param unlockLv 未激活时的解锁所需英雄等级(用于"x级解锁"展示,与技能等级 s_lv 解耦)
*/ */
private addSkillIcon(s_uuid: number, s_lv: number, locked: boolean, isField: boolean, slot?: SkillTriggerType, isGroup: boolean = false, normalLv2: boolean = false) { private addSkillIcon(s_uuid: number, s_lv: number, locked: boolean, isField: boolean, slot?: SkillTriggerType, isGroup: boolean = false, normalLv2: boolean = false, unlockLv?: number) {
const node = instantiate(this.skill_icon_prefab) const node = instantiate(this.skill_icon_prefab)
node.name = `skill_${s_uuid}` node.name = `skill_${s_uuid}`
const comp = node.getComponent(SSkillBoxComp) || node.addComponent(SSkillBoxComp) const comp = node.getComponent(SSkillBoxComp) || node.addComponent(SSkillBoxComp)
// 携带所属英雄与槽位,点击弹窗按英雄技能分档描述渲染 // 携带所属英雄与槽位,点击弹窗按英雄技能分档描述渲染
comp.initHeroSkill(s_uuid, s_lv, locked, isField, this.huuid, slot, isGroup, normalLv2) comp.initHeroSkill(s_uuid, s_lv, locked, isField, this.huuid, slot, isGroup, normalLv2, unlockLv)
this.skills_node.addChild(node) this.skills_node.addChild(node)
} }
@@ -604,7 +657,7 @@ export class HerosListComp extends CCComp {
} }
} }
const pick = active ?? sorted[0] const pick = active ?? sorted[0]
this.addSkillIcon(keys[0], pick.s_lv ?? 1, !anyActive, false, type, true) this.addSkillIcon(keys[0], pick.s_lv ?? 1, !anyActive, false, type, true, false, anyActive ? undefined : pick.lv)
} }
/** /**
@@ -620,7 +673,7 @@ export class HerosListComp extends CCComp {
const firstUuid = pick.uuids[0]?.uuid const firstUuid = pick.uuids[0]?.uuid
if (!firstUuid) return if (!firstUuid) return
// 词条档位无 s_lv 概念,技能等级恒为 1(等级标签展示技能等级而非解锁的英雄等级) // 词条档位无 s_lv 概念,技能等级恒为 1(等级标签展示技能等级而非解锁的英雄等级)
this.addSkillIcon(firstUuid, 1, !active, true, SkillTriggerType.Field, true) this.addSkillIcon(firstUuid, 1, !active, true, SkillTriggerType.Field, true, false, active ? undefined : pick.lv)
} }
/** 复活技能已纳入 dead 触发组,通过 dead 配置展示(revive_hp / revive_count),无需单独处理 */ /** 复活技能已纳入 dead 触发组,通过 dead 配置展示(revive_hp / revive_count),无需单独处理 */
@@ -636,7 +689,7 @@ export class HerosListComp extends CCComp {
const entry = normal?.lv_entries?.[0] const entry = normal?.lv_entries?.[0]
if (!normal || !entry) return if (!normal || !entry) return
// 节点命名区分 lv2 档(普攻与触发槽位可能同底座,uuid 重名会互相干扰) // 节点命名区分 lv2 档(普攻与触发槽位可能同底座,uuid 重名会互相干扰)
this.addSkillIcon(normal.uuid, entry.s_lv ?? 2, lv < entry.lv, false, undefined, false, true) this.addSkillIcon(normal.uuid, entry.s_lv ?? 2, lv < entry.lv, false, undefined, false, true, entry.lv)
const icon = this.skills_node.children[this.skills_node.children.length - 1] const icon = this.skills_node.children[this.skills_node.children.length - 1]
if (icon) icon.name = `skill_${normal.uuid}_lv2` if (icon) icon.name = `skill_${normal.uuid}_lv2`
} }

View File

@@ -66,6 +66,8 @@ export class SSkillBoxComp extends CCComp {
private hero_icon_source?: "skill" | "field"; private hero_icon_source?: "skill" | "field";
/** bonus 档位模式:该图标代表英雄额外属性加成的某一档(图鉴展示,无技能底座 uuid) */ /** bonus 档位模式:该图标代表英雄额外属性加成的某一档(图鉴展示,无技能底座 uuid) */
private bonus_entry?: LvBonusAttrsEntry; private bonus_entry?: LvBonusAttrsEntry;
/** 未激活时的解锁所需英雄等级(用于"x级解锁"展示,与技能等级 rarity 解耦) */
private unlock_lv?: number;
/** 点击事件是否已注册(防止重复绑定) */ /** 点击事件是否已注册(防止重复绑定) */
private _clickRegistered: boolean = false; private _clickRegistered: boolean = false;
@@ -153,13 +155,16 @@ export class SSkillBoxComp extends CCComp {
* 弹窗按整组合并渲染(组内多技能/词条统一说明) * 弹窗按整组合并渲染(组内多技能/词条统一说明)
* @param normalLv2 普攻 lv2+ 强化档专属模式:名称/图标取 lv1,弹窗只展示 lv2+ 档位说明; * @param normalLv2 普攻 lv2+ 强化档专属模式:名称/图标取 lv1,弹窗只展示 lv2+ 档位说明;
* 等级显示偏移一档(配置 Lv2 → 显示 Lv1,Lv3 → 显示 Lv2),强化档从 1 起计 * 等级显示偏移一档(配置 Lv2 → 显示 Lv1,Lv3 → 显示 Lv2),强化档从 1 起计
*/ * @param unlockLv 未激活时的解锁所需英雄等级(触发/光环/强化档未达解锁条件时展示"x级解锁",
initHeroSkill(s_uuid: number, s_lv: number, locked: boolean, isField: boolean = false, heroUuid: number = 0, slot?: SkillTriggerType, isGroup: boolean = false, normalLv2: boolean = false) { * 与技能等级 s_lv 解耦;未传时回退按 rarity 显示)
*/
initHeroSkill(s_uuid: number, s_lv: number, locked: boolean, isField: boolean = false, heroUuid: number = 0, slot?: SkillTriggerType, isGroup: boolean = false, normalLv2: boolean = false, unlockLv?: number) {
this.s_uuid = s_uuid; this.s_uuid = s_uuid;
this.hero_uuid = heroUuid; this.hero_uuid = heroUuid;
this.hero_slot = slot; this.hero_slot = slot;
this.hero_group = isGroup; this.hero_group = isGroup;
this.hero_normal_lv2 = normalLv2; this.hero_normal_lv2 = normalLv2;
this.unlock_lv = unlockLv;
// 普攻 lv2+ 强化档:等级显示偏移一档(配置 Lv2 显示 Lv1,Lv3 显示 Lv2), // 普攻 lv2+ 强化档:等级显示偏移一档(配置 Lv2 显示 Lv1,Lv3 显示 Lv2),
// 强化档作为独立于普攻的技能存在,等级从 1 起计 // 强化档作为独立于普攻的技能存在,等级从 1 起计
this.rarity = normalLv2 ? Math.max(1, s_lv - 1) : s_lv; this.rarity = normalLv2 ? Math.max(1, s_lv - 1) : s_lv;
@@ -170,8 +175,8 @@ export class SSkillBoxComp extends CCComp {
/** /**
* 设置技能激活状态: * 设置技能激活状态:
* - locked = true → 显示锁定遮罩,技能未激活(隐藏等级标签) * - locked = true → 显示锁定遮罩,技能未激活(隐藏等级标签,名称标签显示"x级解锁")
* - locked = false → 隐藏锁定遮罩,技能已激活(恢复等级标签) * - locked = false → 隐藏锁定遮罩,技能已激活(恢复等级标签与技能名)
*/ */
setLocked(locked: boolean) { setLocked(locked: boolean) {
if (this.locked) { if (this.locked) {
@@ -180,6 +185,10 @@ export class SSkillBoxComp extends CCComp {
if (this.lv_label) { if (this.lv_label) {
this.lv_label.node.active = !locked; this.lv_label.node.active = !locked;
} }
if (this.name_label) {
// 未激活时不展示技能名,改为展示解锁条件(优先取英雄等级阈值 unlock_lv,回退技能等级 rarity)
this.name_label.string = locked ? `${this.unlock_lv ?? this.rarity}级解锁` : this.resolveSkillName();
}
} }
/** /**

View File

@@ -6,7 +6,7 @@
* 1. 接收 TalentsComp 下发的天赋配置 + 当前等级 + 阶位解锁态,渲染迷你点选卡。 * 1. 接收 TalentsComp 下发的天赋配置 + 当前等级 + 阶位解锁态,渲染迷你点选卡。
* 2. 卡面自包含:图标 / 名称 / 当前已生效数值(Lv0 显示每级数值引导)/ 右下「当前/满级」角标。 * 2. 卡面自包含:图标 / 名称 / 当前已生效数值(Lv0 显示每级数值引导)/ 右下「当前/满级」角标。
* 3. 阶位背景:普通背景节点下挂 blue / red / yellow 三个颜色子节点,按阶位激活其一(Ⅰ蓝 / Ⅱ红 / Ⅲ金)。 * 3. 阶位背景:普通背景节点下挂 blue / red / yellow 三个颜色子节点,按阶位激活其一(Ⅰ蓝 / Ⅱ红 / Ⅲ金)。
* 4. 状态机:满级(MAX 金角标)/ 未激活(左上锁角标 + 背景与图标灰阶 Grayscale)。 * 4. 状态机:满级(MAX 金角标)/ 未激活(左上锁角标,不再做灰阶处理)。
* 5. 点击回调上抛卡体点击,加点确认弹窗与升级校验统一由 TalentsComp 处理(单一决策点)。 * 5. 点击回调上抛卡体点击,加点确认弹窗与升级校验统一由 TalentsComp 处理(单一决策点)。
* *
* 依赖: * 依赖:
@@ -85,11 +85,11 @@ export class TalentItemComp extends CCComp {
if (this.lbl_info) this.lbl_info.string = getTalentDisplayText(cfg, lv); if (this.lbl_info) this.lbl_info.string = getTalentDisplayText(cfg, lv);
if (this.lbl_lv) this.lbl_lv.string = `${lv}/${cfg.max_lv}`; if (this.lbl_lv) this.lbl_lv.string = `${lv}/${cfg.max_lv}`;
// 未激活(Lv0 或阶位未解锁):背景与图标灰阶 // 未激活(Lv0 或阶位未解锁):仅显示 node_lock 锁遮罩,不做灰阶处理
const inactive = lv <= 0 || !tierUnlocked; const inactive = lv <= 0 || !tierUnlocked;
// 阶位背景:激活对应颜色子节点(Ⅰ蓝 / Ⅱ红 / Ⅲ金) // 阶位背景:激活对应颜色子节点(Ⅰ蓝 / Ⅱ红 / Ⅲ金)
if (this.bg) this.applyTierBg(cfg.tier, inactive); if (this.bg) this.applyTierBg(cfg.tier);
// 图标:技能图标图集(gui/ui7)优先,资源目录回退(与 SCardComp 口径一致) // 图标:技能图标图集(gui/ui7)优先,资源目录回退(与 SCardComp 口径一致)
if (this.icon && cfg.icon) { if (this.icon && cfg.icon) {
@@ -101,7 +101,6 @@ export class TalentItemComp extends CCComp {
frame = oops.res.get("game/heros/cards/" + cfg.icon, SpriteFrame) as SpriteFrame; frame = oops.res.get("game/heros/cards/" + cfg.icon, SpriteFrame) as SpriteFrame;
} }
if (frame) this.icon.spriteFrame = frame; if (frame) this.icon.spriteFrame = frame;
this.icon.grayscale = inactive;
} }
// 状态角标:满级 MAX / 未激活锁角标(未加点或阶位未解锁,置于左上角) // 状态角标:满级 MAX / 未激活锁角标(未加点或阶位未解锁,置于左上角)
@@ -109,16 +108,13 @@ export class TalentItemComp extends CCComp {
if (this.node_lock) this.node_lock.active = inactive; if (this.node_lock) this.node_lock.active = inactive;
} }
/** 按阶位激活 bg 下对应颜色子节点,其余隐藏;未激活时全部开启灰阶 */ /** 按阶位激活 bg 下对应颜色子节点,其余隐藏 */
private applyTierBg(tier: TalentTier, inactive: boolean): void { private applyTierBg(tier: TalentTier): void {
const curName = TIER_BG_CHILD_NAMES[tier]; const curName = TIER_BG_CHILD_NAMES[tier];
for (const [, name] of Object.entries(TIER_BG_CHILD_NAMES)) { for (const [, name] of Object.entries(TIER_BG_CHILD_NAMES)) {
const child = this.bg.getChildByName(name); const child = this.bg.getChildByName(name);
if (!child) continue; if (!child) continue;
child.active = name === curName; child.active = name === curName;
// Sprite 内置灰阶材质,未激活天赋的背景置灰
const render = child.getComponent(Sprite);
if (render) render.grayscale = inactive;
} }
} }