4 Commits

Author SHA1 Message Date
panFD
d7cd440844 chore: 修改 git 提交规则配置中的 alwaysApply 为 false
调整 git 提交规则配置文件,将 alwaysApply 字段从 true 修改为 false
2026-10-10 08:46:32 +08:00
panFD
a242ccc2ea feat(heros): 为多个英雄预制件添加外发光材质组件 2026-10-10 08:43:55 +08:00
panFD
74d03facd9 fix(boss): keep phase outline authoritative over level tint and pool reuse
Reuse existing outline-green/outline-glow materials (P2 green / P3 red); phase outline now takes priority over level tint during boss lifetime (init/lv_up both route through BossPhaseComp), and HeroViewComp.reset clears the material back to default so pooled monster nodes never inherit a boss's red/green edge.
2026-10-10 00:40:47 +08:00
panFD
a122d0904c feat(boss): tint boss sprite outline by phase (P2 green, P3 red)
Add FlashSprite.setOutlineByBossPhase with light/dark green shade option and red fallback; BossPhaseSystem drives HeroViewComp.applyBossPhaseOutline directly after phase switch (MON faction, no hero-level event semantics, pool-node safe); extract getFlashSprite/applyOutlineByLevel to dedupe the three outline call sites.
2026-10-10 00:33:41 +08:00
10 changed files with 112 additions and 22 deletions

View File

@@ -1,8 +1,7 @@
--- ---
alwaysApply: true alwaysApply: false
scene: git_message scene: git_message
--- ---
## Profile ## Profile
你是一个严谨的配置管理专家与代码审查员。你的核心任务是根据代码的变更内容(diff)或开发者的简短描述,生成符合业界标准(Conventional Commits / Angular 规范)的 Git 提交信息。你擅长剥离代码细节,总结出清晰的业务意图(What 和 Why)。 你是一个严谨的配置管理专家与代码审查员。你的核心任务是根据代码的变更内容(diff)或开发者的简短描述,生成符合业界标准(Conventional Commits / Angular 规范)的 Git 提交信息。你擅长剥离代码细节,总结出清晰的业务意图(What 和 Why)。

View File

@@ -402,6 +402,10 @@
"__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde", "__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde",
"__expectedType__": "cc.Material" "__expectedType__": "cc.Material"
}, },
"outlineMatGlow": {
"__uuid__": "2fcd55a9-38ca-45aa-9164-68e48aaf51ce",
"__expectedType__": "cc.Material"
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -402,6 +402,10 @@
"__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde", "__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde",
"__expectedType__": "cc.Material" "__expectedType__": "cc.Material"
}, },
"outlineMatGlow": {
"__uuid__": "2fcd55a9-38ca-45aa-9164-68e48aaf51ce",
"__expectedType__": "cc.Material"
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -402,6 +402,10 @@
"__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde", "__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde",
"__expectedType__": "cc.Material" "__expectedType__": "cc.Material"
}, },
"outlineMatGlow": {
"__uuid__": "2fcd55a9-38ca-45aa-9164-68e48aaf51ce",
"__expectedType__": "cc.Material"
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -402,6 +402,10 @@
"__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde", "__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde",
"__expectedType__": "cc.Material" "__expectedType__": "cc.Material"
}, },
"outlineMatGlow": {
"__uuid__": "2fcd55a9-38ca-45aa-9164-68e48aaf51ce",
"__expectedType__": "cc.Material"
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -402,6 +402,10 @@
"__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde", "__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde",
"__expectedType__": "cc.Material" "__expectedType__": "cc.Material"
}, },
"outlineMatGlow": {
"__uuid__": "2fcd55a9-38ca-45aa-9164-68e48aaf51ce",
"__expectedType__": "cc.Material"
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -402,6 +402,10 @@
"__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde", "__uuid__": "2b8a37ee-732c-4c5b-b6a4-136f3e581cde",
"__expectedType__": "cc.Material" "__expectedType__": "cc.Material"
}, },
"outlineMatGlow": {
"__uuid__": "2fcd55a9-38ca-45aa-9164-68e48aaf51ce",
"__expectedType__": "cc.Material"
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -19,6 +19,7 @@ import { SkillSet } from "../common/config/SkillSet";
import { mLogger } from "../common/Logger"; import { mLogger } from "../common/Logger";
import { HeroAttrsComp } from "./HeroAttrsComp"; import { HeroAttrsComp } from "./HeroAttrsComp";
import { BossPhaseComp } from "./BossPhaseComp"; import { BossPhaseComp } from "./BossPhaseComp";
import { HeroViewComp } from "./HeroViewComp";
/** 阶段模块调试日志开关 */ /** 阶段模块调试日志开关 */
const DEBUG = true; const DEBUG = true;
@@ -119,6 +120,13 @@ export class BossPhaseSystem extends ecs.ComblockSystem implements ecs.ISystemUp
fromPhase: from, fromPhase: from,
toPhase: phase.index, toPhase: phase.index,
}); });
// 直接驱动描边:Boss 是 MON 阵营,不走英雄 HeroLvUp 语义;
// 且对象池节点上挂全局事件监听易漏注销,直接调视图组件最稳
const view = e.get(HeroViewComp);
if (view && view.node && view.node.isValid) {
view.applyBossPhaseOutline(phase.index);
}
} }
/** TODO: 阶段退场表现(震屏/变暗等),后续迭代实现 */ /** TODO: 阶段退场表现(震屏/变暗等),后续迭代实现 */

View File

@@ -16,6 +16,7 @@ import { Tooltip } from "../skill/Tooltip";
import { timedCom } from "../skill/timedCom"; import { timedCom } from "../skill/timedCom";
import { oneCom } from "../skill/oncend"; import { oneCom } from "../skill/oncend";
import { FlashSprite } from "./hit-flash-white/scripts/FlashSprite"; import { FlashSprite } from "./hit-flash-white/scripts/FlashSprite";
import { BossPhaseComp } from "./BossPhaseComp";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@@ -89,7 +90,6 @@ export class HeroViewComp extends CCComp {
this.deadCD = 0; this.deadCD = 0;
this.lastBarUpdateTime = 0; this.lastBarUpdateTime = 0;
this.status_change("idle"); this.status_change("idle");
// 初始化头顶状态栏 // 初始化头顶状态栏
const topNode = this.node.getChildByName("top"); const topNode = this.node.getChildByName("top");
this.topBar = topNode.getComponent(HeroTopBarComp) || topNode.addComponent(HeroTopBarComp); this.topBar = topNode.getComponent(HeroTopBarComp) || topNode.addComponent(HeroTopBarComp);
@@ -98,15 +98,12 @@ export class HeroViewComp extends CCComp {
/** 方向 */ /** 方向 */
this.node.setScale(this.scale * Math.abs(this.node.scale.x), 1 * this.node.scale.y); // 确保 scale.x 为正后再乘方向 this.node.setScale(this.scale * Math.abs(this.node.scale.x), 1 * this.node.scale.y); // 确保 scale.x 为正后再乘方向
// 🔥 重置描边 // 🔥 重置描边:Boss 阶段描边优先(Boss 存活期不被等级描边覆盖),其余按等级
if (this.model) { const phaseComp = this.ent ? this.ent.get(BossPhaseComp) : null;
let flashSprite = this.node.getComponent(FlashSprite); if (phaseComp && phaseComp.index > 0) {
if (!flashSprite) { this.applyBossPhaseOutline(phaseComp.index);
flashSprite = this.node.getComponentInChildren(FlashSprite); } else {
} this.applyOutlineByLevel();
if (flashSprite) {
flashSprite.setOutlineByLevel(this.model.lv);
}
} }
} }
@@ -170,16 +167,40 @@ export class HeroViewComp extends CCComp {
public lv_up() { public lv_up() {
this.spawnTimedFx("game/skill/buff/buff_lvup", this.node, 1.0); this.spawnTimedFx("game/skill/buff/buff_lvup", this.node, 1.0);
// 升级时同步更新描边 // 升级时同步更新描边:Boss 阶段描边优先(与 init 口径一致)
if (this.model) { const phaseComp = this.ent ? this.ent.get(BossPhaseComp) : null;
let flashSprite = this.node.getComponent(FlashSprite); if (phaseComp && phaseComp.index > 0) {
if (!flashSprite) { this.applyBossPhaseOutline(phaseComp.index);
flashSprite = this.node.getComponentInChildren(FlashSprite); } else {
this.applyOutlineByLevel();
} }
}
/** 按英雄等级应用描边(升级/初始化共用入口) */
private applyOutlineByLevel() {
if (!this.model) return;
const flashSprite = this.getFlashSprite();
if (flashSprite) { if (flashSprite) {
flashSprite.setOutlineByLevel(this.model.lv); flashSprite.setOutlineByLevel(this.model.lv);
} }
} }
/**
* 按 Boss 阶段应用描边(P2 绿 / P3 红)
* Why: 由 BossPhaseSystem 直接调用,不走英雄 HeroLvUp 事件语义
* (Boss 是 MON 阵营,且对象池节点挂全局监听易漏注销)
* @param phase 阶段索引:1=P2 / 2=P3
*/
public applyBossPhaseOutline(phase: number) {
const flashSprite = this.getFlashSprite();
if (flashSprite) {
flashSprite.setOutlineByBossPhase(phase);
}
}
/** 查找 FlashSprite 组件(优先自身,回退子节点),描边三处调用点统一入口 */
private getFlashSprite(): FlashSprite | null {
return this.node.getComponent(FlashSprite) ?? this.node.getComponentInChildren(FlashSprite);
} }
/** 攻击力提升特效 */ /** 攻击力提升特效 */
@@ -566,6 +587,13 @@ export class HeroViewComp extends CCComp {
this.deadCD = 0 this.deadCD = 0
this.lastBarUpdateTime = 0 this.lastBarUpdateTime = 0
// 清掉描边材质:防 Boss 阶段描边(绿/红)随对象池节点复用串到小怪/英雄身上
const flashSprite = this.getFlashSprite();
if (flashSprite && flashSprite.defaultMaterial) {
flashSprite.orginalFlashMaterial = flashSprite.defaultMaterial;
flashSprite.sprite?.setSharedMaterial(flashSprite.defaultMaterial, 0);
}
// 清理伤害队列 // 清理伤害队列
this.damageQueue.length = 0; this.damageQueue.length = 0;
this.isProcessingDamage = false; this.isProcessingDamage = false;

View File

@@ -7,7 +7,7 @@ export class FlashSprite extends Component {
@property(Material) @property(Material)
hitFlashMaterial: Material | null = null; hitFlashMaterial: Material | null = null;
@property({ type: Material, tooltip: '绿色描边材质(2级)' }) @property({ type: Material, tooltip: '绿色描边材质(2级 / Boss阶段2)' })
outlineMatGreen: Material | null = null; outlineMatGreen: Material | null = null;
@property({ type: Material, tooltip: '蓝色描边材质(3级)' }) @property({ type: Material, tooltip: '蓝色描边材质(3级)' })
@@ -19,6 +19,9 @@ export class FlashSprite extends Component {
@property({ type: Material, tooltip: '黄色描边材质(5级)' }) @property({ type: Material, tooltip: '黄色描边材质(5级)' })
outlineMatYellow: Material | null = null; outlineMatYellow: Material | null = null;
@property({ type: Material, tooltip: '红色描边材质(Boss阶段3,即 outline-glow)' })
outlineMatGlow: Material | null = null;
orginalFlashMaterial: Material | null = null; orginalFlashMaterial: Material | null = null;
defaultMaterial: Material | null = null; // 缓存最原始的无描边材质 defaultMaterial: Material | null = null; // 缓存最原始的无描边材质
sprite: Sprite | null = null; sprite: Sprite | null = null;
@@ -64,6 +67,34 @@ export class FlashSprite extends Component {
} }
} }
/**
* 按 Boss 阶段设置描边材质(优先级高于等级描边)
* Why: Boss 阶段是战斗强反馈(P2 绿=警告 / P3 红=危险),与英雄等级成长是两套视觉语言,
* 用独立通道避免污染 setOutlineByLevel 的等级语义;材质复用现有 outline-green / outline-glow
* @param phase 阶段索引:1=P2 绿 / 2=P3 红 / 0=P1 恢复默认
*/
public setOutlineByBossPhase(phase: number) {
if (!this.sprite) {
this.sprite = this.node.getComponent(Sprite);
}
if (!this.sprite) return;
let targetMat: Material | null = null;
if (phase === 1) {
targetMat = this.outlineMatGreen;
} else if (phase >= 2) {
targetMat = this.outlineMatGlow ?? this.outlineMatYellow;
} else {
targetMat = this.defaultMaterial;
}
if (targetMat) {
// 更新基础材质,确保闪白结束后恢复到这个阶段描边材质
this.orginalFlashMaterial = targetMat;
this.sprite.setSharedMaterial(targetMat, 0);
}
}
public clickFlash() { public clickFlash() {
if (!this.sprite || !this.hitFlashMaterial) return; if (!this.sprite || !this.hitFlashMaterial) return;