From b31d870d9023ddbcdebf9db5857c60fe921522f8 Mon Sep 17 00:00:00 2001 From: panFD Date: Sat, 10 Oct 2026 00:25:23 +0800 Subject: [PATCH] feat(boss): tint boss outline green in phase 2 and red in phase 3 Add FlashSprite.setPhaseOutline (P1 default / P2 green / P3 red) and drive it from BossPhaseSystem.onPhaseEnter; reset outline on pooled boss reuse so stale tint never leaks to the next owner. Red outline material asset must be created in editor (copy green, tint red) and bound to FlashSprite.outlineMatRed. --- assets/script/game/hero/BossPhaseSystem.ts | 18 ++++++++++-- assets/script/game/hero/HeroViewComp.ts | 11 ++++++++ assets/script/game/hero/Mon.ts | 4 +++ .../hit-flash-white/scripts/FlashSprite.ts | 28 +++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/assets/script/game/hero/BossPhaseSystem.ts b/assets/script/game/hero/BossPhaseSystem.ts index 53d3dea0..dfbcd25d 100644 --- a/assets/script/game/hero/BossPhaseSystem.ts +++ b/assets/script/game/hero/BossPhaseSystem.ts @@ -18,7 +18,9 @@ import { BossPhaseSet, PhaseSwitchDef } from "../common/config/BossPhaseSet"; import { SkillSet } from "../common/config/SkillSet"; import { mLogger } from "../common/Logger"; import { HeroAttrsComp } from "./HeroAttrsComp"; +import { HeroViewComp } from "./HeroViewComp"; import { BossPhaseComp } from "./BossPhaseComp"; +import { FlashSprite } from "./hit-flash-white/scripts/FlashSprite"; /** 阶段模块调试日志开关 */ const DEBUG = true; @@ -124,6 +126,18 @@ export class BossPhaseSystem extends ecs.ComblockSystem implements ecs.ISystemUp /** TODO: 阶段退场表现(震屏/变暗等),后续迭代实现 */ private onPhaseExit(e: ecs.Entity): void { } - /** TODO: 阶段入场表现(怒吼/无敌帧/技能横幅等),后续迭代实现 */ - private onPhaseEnter(e: ecs.Entity): void { } + /** 阶段入场表现:切换阶段描边(P2 绿 / P3 红);怒吼/无敌帧/横幅等后续迭代 */ + private onPhaseEnter(e: ecs.Entity): void { + const view = e.get(HeroViewComp); + if (!view || !view.node || !view.node.isValid) return; + const phase = e.get(BossPhaseComp)!; + // FlashSprite 可能在根节点或子节点(anm)上,逐级查找 + let flash = view.node.getComponent(FlashSprite); + if (!flash) { + flash = view.node.getComponentInChildren(FlashSprite); + } + if (flash) { + flash.setPhaseOutline(phase.index); + } + } } diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index ad23fd2c..ee369af2 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -576,6 +576,17 @@ export class HeroViewComp extends CCComp { // } } + /** 复位阶段描边为默认(Boss 池化复用必经路径,防红/绿描边残留到下一个复用者) */ + public resetPhaseOutline() { + let flash = this.node.getComponent(FlashSprite); + if (!flash) { + flash = this.node.getComponentInChildren(FlashSprite); + } + if (flash) { + flash.setPhaseOutline(0); + } + } + } diff --git a/assets/script/game/hero/Mon.ts b/assets/script/game/hero/Mon.ts index 3d901d0a..2fb204fa 100644 --- a/assets/script/game/hero/Mon.ts +++ b/assets/script/game/hero/Mon.ts @@ -290,6 +290,10 @@ export class Monster extends ecs.Entity { // 注册视图组件并重置对象池复用状态 this.add(view); view.init(); + // 阶段 Boss:init 按 lv 设的等级描边与阶段描边冲突,复位为 P1 无描边(P2/P3 由 BossPhaseSystem 再上色) + if (this.has(BossPhaseComp)) { + view.resetPhaseOutline(); + } view.as.idle(); // 广播怪物加载事件,供刷怪与战斗系统联动 oops.message.dispatchEvent("monster_load", this) diff --git a/assets/script/game/hero/hit-flash-white/scripts/FlashSprite.ts b/assets/script/game/hero/hit-flash-white/scripts/FlashSprite.ts index 45645a09..fe689e79 100644 --- a/assets/script/game/hero/hit-flash-white/scripts/FlashSprite.ts +++ b/assets/script/game/hero/hit-flash-white/scripts/FlashSprite.ts @@ -19,6 +19,9 @@ export class FlashSprite extends Component { @property({ type: Material, tooltip: '黄色描边材质(5级)' }) outlineMatYellow: Material | null = null; + @property({ type: Material, tooltip: '红色描边材质(Boss阶段3)' }) + outlineMatRed: Material | null = null; + orginalFlashMaterial: Material | null = null; defaultMaterial: Material | null = null; // 缓存最原始的无描边材质 sprite: Sprite | null = null; @@ -64,6 +67,31 @@ export class FlashSprite extends Component { } } + /** + * 设置 Boss 阶段描边(与等级描边互斥,阶段优先) + * @param phase 阶段索引 0=P1(无描边/恢复默认) 1=P2(绿) 2=P3(红) + */ + public setPhaseOutline(phase: number) { + if (!this.sprite) { + this.sprite = this.node.getComponent(Sprite); + } + + let targetMat: Material | null = null; + if (phase === 1) { + targetMat = this.outlineMatGreen; + } else if (phase >= 2) { + targetMat = this.outlineMatRed; + } else { + // P1 / 复位:恢复最原始的无描边材质 + targetMat = this.defaultMaterial; + } + + if (targetMat && this.sprite) { + this.orginalFlashMaterial = targetMat; + this.sprite.setSharedMaterial(targetMat, 0); + } + } + public clickFlash() { if (!this.sprite || !this.hitFlashMaterial) return;