feat(herolist&skillbox): 新增英雄图鉴技能图标展示功能
1. 为SSkillBoxComp新增英雄图鉴专用初始化方法,支持区分技能/驻场光环图标来源 2. 扩展技能背景色适配,支持5档英雄技能等级配色 3. 在HerosListComp中实现英雄技能图标列表刷新逻辑,支持大招和各类触发技能展示 4. 按英雄等级动态显示技能解锁状态和对应等级图标
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -22,12 +22,13 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
|
|||||||
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 } from "../common/config/heroSet";
|
import { HeroInfo, HeroList, SkillTriggerType, LvFieldEntry, LvReviveEntry, LvTriggerEntry, TriggerGrouped } from "../common/config/heroSet";
|
||||||
import { buildSkillDesc } from "../common/config/HeroSkillDesc";
|
import { buildSkillDesc } from "../common/config/HeroSkillDesc";
|
||||||
import { GameEvent } from "../common/config/GameEvent";
|
import { GameEvent } from "../common/config/GameEvent";
|
||||||
import { HERO_UPGRADE_NEED_FRAGMENTS, CARD_LV_BG_COLORS } from "../common/config/GameSet";
|
import { HERO_UPGRADE_NEED_FRAGMENTS, CARD_LV_BG_COLORS } from "../common/config/GameSet";
|
||||||
import { CardLiteComp } from "./CardLiteComp";
|
import { CardLiteComp } from "./CardLiteComp";
|
||||||
import { ChipComp } from "./ChipComp";
|
import { ChipComp } from "./ChipComp";
|
||||||
|
import { SSkillBoxComp } from "./SSkillBoxComp";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
|
|
||||||
const { property, ccclass } = _decorator;
|
const { property, ccclass } = _decorator;
|
||||||
@@ -90,6 +91,14 @@ export class HerosListComp extends CCComp {
|
|||||||
/** 技能描述节点() */
|
/** 技能描述节点() */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
infos_node = null!
|
infos_node = null!
|
||||||
|
|
||||||
|
/** 技能图标容器节点(动态挂载 SSkillBoxComp 实例,展示当前英雄技能) */
|
||||||
|
@property(Node)
|
||||||
|
skills_node = null!
|
||||||
|
|
||||||
|
/** 技能小图标预制体(根节点挂 SSkillBoxComp) */
|
||||||
|
@property(Prefab)
|
||||||
|
skill_icon_prefab = null!
|
||||||
/** 升级特效动画节点(内含升级效果 Animation,点击升级时从头播放) */
|
/** 升级特效动画节点(内含升级效果 Animation,点击升级时从头播放) */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
upgrade_anim_node = null!
|
upgrade_anim_node = null!
|
||||||
@@ -408,6 +417,7 @@ export class HerosListComp extends CCComp {
|
|||||||
this.updateTypeDisplay(hero)
|
this.updateTypeDisplay(hero)
|
||||||
this.updateHeroAnimation(uuid)
|
this.updateHeroAnimation(uuid)
|
||||||
this.updateGrowthPanel(uuid)
|
this.updateGrowthPanel(uuid)
|
||||||
|
this.updateSkillIcons(hero)
|
||||||
}
|
}
|
||||||
|
|
||||||
private updatePoolLvBg(card_lv: number) {
|
private updatePoolLvBg(card_lv: number) {
|
||||||
@@ -476,6 +486,112 @@ export class HerosListComp extends CCComp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ======================== 技能图标列表 ========================
|
||||||
|
|
||||||
|
/** 图鉴面板展示的触发技能类型(heroInfo 触发配置:死亡/战斗开始/光环/攻击后/受击/复活) */
|
||||||
|
private static readonly PANEL_TRIGGER_TYPES: SkillTriggerType[] = [
|
||||||
|
SkillTriggerType.Dead,
|
||||||
|
SkillTriggerType.FStart,
|
||||||
|
SkillTriggerType.Field,
|
||||||
|
SkillTriggerType.Atking,
|
||||||
|
SkillTriggerType.Atked,
|
||||||
|
SkillTriggerType.Revive,
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新当前英雄的技能图标列表:
|
||||||
|
* 1. 大招:skills[1] 及以后(首个为普攻,跳过)。
|
||||||
|
* 2. 触发技能:Dead/FStart/Field/Atking/Atked/Revive。
|
||||||
|
* 以局外等级(getHeroOuterLv)为当前等级,未达解锁档的显示 locked,
|
||||||
|
* 已激活的显示当前等级对应的技能等级。
|
||||||
|
*/
|
||||||
|
private updateSkillIcons(hero: typeof HeroInfo[number]) {
|
||||||
|
if (!this.skills_node || !this.skill_icon_prefab) return
|
||||||
|
|
||||||
|
// 清空旧图标(显式销毁,避免节点泄漏)
|
||||||
|
for (let i = this.skills_node.children.length - 1; i >= 0; i--) {
|
||||||
|
this.skills_node.children[i].destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
const lv = Math.max(1, smc.getHeroOuterLv(hero.uuid))
|
||||||
|
|
||||||
|
// ---- 大招:skills[1] 及以后 ----
|
||||||
|
Object.values(hero.skills).slice(1).forEach(hSkill => {
|
||||||
|
// 与 Hero.load 同式:技能等级 = 配置 lv + 英雄等级 - 2,> 0 才视为已解锁
|
||||||
|
const unlocked = hSkill.lv + lv - 2 > 0
|
||||||
|
// 技能等级展示与 buildSkillDesc 同规则:lv_entries 取 ≤lv 最大档的 s_lv
|
||||||
|
const sLv = hSkill.lv_entries?.length
|
||||||
|
? (hSkill.lv_entries.filter(e => e.lv <= lv).pop()?.s_lv ?? hSkill.lv)
|
||||||
|
: hSkill.lv
|
||||||
|
this.addSkillIcon(hSkill.uuid, sLv, !unlocked, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// ---- 触发技能:按 PANEL_TRIGGER_TYPES 顺序追加 ----
|
||||||
|
for (const type of HerosListComp.PANEL_TRIGGER_TYPES) {
|
||||||
|
if (type === SkillTriggerType.Field) {
|
||||||
|
this.addFieldIcons(hero[SkillTriggerType.Field], lv)
|
||||||
|
} else if (type === SkillTriggerType.Revive) {
|
||||||
|
this.addReviveIcon(hero[SkillTriggerType.Revive], lv)
|
||||||
|
} else {
|
||||||
|
this.addTriggerIcons(hero[type] as TriggerGrouped | undefined, lv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化技能小图标并初始化
|
||||||
|
* @param s_uuid 技能 UUID(SkillSet 或 FieldSkillSet)
|
||||||
|
* @param s_lv 当前等级对应的技能等级(locked 时为解锁预览档)
|
||||||
|
* @param locked 当前等级未激活 → 显示锁定遮罩
|
||||||
|
* @param isField true 表示驻场光环词条(图标取 FieldSkillSet)
|
||||||
|
*/
|
||||||
|
private addSkillIcon(s_uuid: number, s_lv: number, locked: boolean, isField: boolean) {
|
||||||
|
const node = instantiate(this.skill_icon_prefab)
|
||||||
|
node.name = `skill_${s_uuid}`
|
||||||
|
const comp = node.getComponent(SSkillBoxComp) || node.addComponent(SSkillBoxComp)
|
||||||
|
comp.initHeroSkill(s_uuid, s_lv, locked, isField)
|
||||||
|
this.skills_node.addChild(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发技能(dead/fstart/atking/atked):按 s_uuid 分组,取 ≤lv 最大档判定激活;
|
||||||
|
* 未激活时预览最低档(与 resolveTriggerByLv 同语义)
|
||||||
|
*/
|
||||||
|
private addTriggerIcons(grouped: TriggerGrouped | undefined, lv: number) {
|
||||||
|
if (!grouped) return
|
||||||
|
for (const key in grouped) {
|
||||||
|
const entries = grouped[key]
|
||||||
|
if (!entries?.length) continue
|
||||||
|
const sorted = [...entries].sort((a, b) => a.lv - b.lv)
|
||||||
|
let active: LvTriggerEntry | undefined
|
||||||
|
for (const e of sorted) { if (e.lv <= lv) active = e }
|
||||||
|
const pick = active ?? sorted[0]
|
||||||
|
this.addSkillIcon(Number(key), pick.s_lv ?? 1, !active, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 驻场光环:未激活取最低档预览,激活取 ≤lv 最大档的词条列表 */
|
||||||
|
private addFieldIcons(field: LvFieldEntry[] | undefined, lv: number) {
|
||||||
|
if (!field?.length) return
|
||||||
|
const sorted = [...field].sort((a, b) => a.lv - b.lv)
|
||||||
|
let active: LvFieldEntry | undefined
|
||||||
|
for (const e of sorted) { if (e.lv <= lv) active = e }
|
||||||
|
const pick = active ?? sorted[0]
|
||||||
|
for (const entry of pick.uuids) {
|
||||||
|
this.addSkillIcon(entry.uuid, pick.lv, !active, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 复活技能:未激活取最低档预览,激活取 ≤lv 最大档 */
|
||||||
|
private addReviveIcon(revive: LvReviveEntry[] | undefined, lv: number) {
|
||||||
|
if (!revive?.length) return
|
||||||
|
const sorted = [...revive].sort((a, b) => a.lv - b.lv)
|
||||||
|
let active: LvReviveEntry | undefined
|
||||||
|
for (const e of sorted) { if (e.lv <= lv) active = e }
|
||||||
|
const pick = active ?? sorted[0]
|
||||||
|
this.addSkillIcon(pick.s_uuid, pick.lv, !active, false)
|
||||||
|
}
|
||||||
|
|
||||||
// ======================== 英雄动画 ========================
|
// ======================== 英雄动画 ========================
|
||||||
|
|
||||||
private updateHeroAnimation(uuid: number) {
|
private updateHeroAnimation(uuid: number) {
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ export class SSkillBoxComp extends CCComp {
|
|||||||
private trigger_type: CardTriggerType = CardTriggerType.Instant;
|
private trigger_type: CardTriggerType = CardTriggerType.Instant;
|
||||||
/** 驻场技能词条列表(uuid 指向 FieldSkillSet 底座,value 为生效数值) */
|
/** 驻场技能词条列表(uuid 指向 FieldSkillSet 底座,value 为生效数值) */
|
||||||
public field: FieldEntry[] = [];
|
public field: FieldEntry[] = [];
|
||||||
|
/** 英雄图鉴模式下的图标来源:skill=SkillSet,field=FieldSkillSet;undefined 表示装备卡模式 */
|
||||||
|
private hero_icon_source?: "skill" | "field";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化技能卡效果:
|
* 初始化技能卡效果:
|
||||||
@@ -69,6 +71,22 @@ export class SSkillBoxComp extends CCComp {
|
|||||||
this.updateUI();
|
this.updateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化英雄技能图标(英雄图鉴面板专用):
|
||||||
|
* 图标按 s_uuid 直接取 SkillSet / FieldSkillSet 配置,不走 EquipPoolList。
|
||||||
|
* @param s_uuid 技能 UUID(大招/触发技能指向 SkillSet,光环词条指向 FieldSkillSet)
|
||||||
|
* @param s_lv 当前英雄等级下生效的技能等级(显示在等级标签)
|
||||||
|
* @param locked 当前等级未激活时显示锁定遮罩
|
||||||
|
* @param isField true 时图标取 FieldSkillSet(驻场光环词条)
|
||||||
|
*/
|
||||||
|
initHeroSkill(s_uuid: number, s_lv: number, locked: boolean, isField: boolean = false) {
|
||||||
|
this.s_uuid = s_uuid;
|
||||||
|
this.card_lv = s_lv;
|
||||||
|
this.hero_icon_source = isField ? "field" : "skill";
|
||||||
|
this.updateUI();
|
||||||
|
this.setLocked(locked);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置技能激活状态:
|
* 设置技能激活状态:
|
||||||
* - locked = true → 显示锁定遮罩,技能未激活
|
* - locked = true → 显示锁定遮罩,技能未激活
|
||||||
@@ -82,10 +100,9 @@ export class SSkillBoxComp extends CCComp {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据技能等级切换 bg_node 下的颜色子节点显示。
|
* 根据技能等级切换 bg_node 下的颜色子节点显示。
|
||||||
* 等级与颜色对应关系(技能卡 wave 档位):
|
* 等级与颜色对应关系:
|
||||||
* card_lv 1 (wave 1) → green
|
* 技能卡档位:card_lv 1 (wave 1) → green,2 (wave 5) → blue,3 (wave 8) → purple
|
||||||
* card_lv 2 (wave 5) → blue
|
* 英雄技能等级:s_lv 1~5 → green / blue / purple / red / yellow
|
||||||
* card_lv 3 (wave 8) → purple
|
|
||||||
*/
|
*/
|
||||||
private updateBgNode() {
|
private updateBgNode() {
|
||||||
if (!this.bg_node) return;
|
if (!this.bg_node) return;
|
||||||
@@ -93,6 +110,8 @@ export class SSkillBoxComp extends CCComp {
|
|||||||
1: "green",
|
1: "green",
|
||||||
2: "blue",
|
2: "blue",
|
||||||
3: "purple",
|
3: "purple",
|
||||||
|
4: "red",
|
||||||
|
5: "yellow",
|
||||||
};
|
};
|
||||||
const targetColor = lvToColor[this.card_lv];
|
const targetColor = lvToColor[this.card_lv];
|
||||||
this.bg_node.children.forEach(child => {
|
this.bg_node.children.forEach(child => {
|
||||||
@@ -112,10 +131,16 @@ export class SSkillBoxComp extends CCComp {
|
|||||||
|
|
||||||
// 加载技能图标
|
// 加载技能图标
|
||||||
if (this.icon_node) {
|
if (this.icon_node) {
|
||||||
// 优先使用卡牌自定义 icon;未定义则按 trigger_type 自动取
|
// 优先使用卡牌自定义 icon;未定义则按图鉴模式 / 装备卡 trigger_type 自动取
|
||||||
let iconId: string | undefined = this.card_icon;
|
let iconId: string | undefined = this.card_icon;
|
||||||
if (!iconId) {
|
if (!iconId) {
|
||||||
if (this.trigger_type === CardTriggerType.Interval) {
|
if (this.hero_icon_source === "field") {
|
||||||
|
// 英雄图鉴:驻场光环词条图标取 FieldSkillSet
|
||||||
|
iconId = this.s_uuid ? FieldSkillSet[this.s_uuid]?.icon : undefined;
|
||||||
|
} else if (this.hero_icon_source === "skill") {
|
||||||
|
// 英雄图鉴:大招/触发技能图标取 SkillSet
|
||||||
|
iconId = this.s_uuid ? SkillSet[this.s_uuid]?.icon : undefined;
|
||||||
|
} else if (this.trigger_type === CardTriggerType.Interval) {
|
||||||
iconId = this.s_uuid ? SkillSet[this.s_uuid]?.icon : undefined;
|
iconId = this.s_uuid ? SkillSet[this.s_uuid]?.icon : undefined;
|
||||||
} else if (this.trigger_type === CardTriggerType.Field) {
|
} else if (this.trigger_type === CardTriggerType.Field) {
|
||||||
const fieldUuid = this.field?.[0]?.uuid;
|
const fieldUuid = this.field?.[0]?.uuid;
|
||||||
|
|||||||
Reference in New Issue
Block a user