From d2418c03c82986c823fe3081af56be638bdd161b Mon Sep 17 00:00:00 2001 From: panw Date: Fri, 13 Mar 2026 10:21:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(buff):=20=E6=96=B0=E5=A2=9E=E9=97=B4?= =?UTF-8?q?=E9=9A=94=E8=A7=A6=E5=8F=91=E5=9E=8Bbuff=E6=95=88=E6=9E=9C?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 SkillSet.ts 中添加 BuffRunType 枚举和 interval 配置字段 - 在 HeroAttrsComp 中实现间隔效果处理逻辑,支持持续治疗和流血等效果 - 新增 INTERVAL_EFFECTS 数组和 updateIntervalEffectsBySystem 方法来管理间隔触发 - 添加 10311(持续治疗)和 10312(流血)两个示例buff配置 --- assets/script/game/common/config/SkillSet.ts | 9 ++ assets/script/game/hero/HeroAttrsComp.ts | 111 +++++++++++++++---- 2 files changed, 101 insertions(+), 19 deletions(-) diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 9948069c..ce3ab7c9 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -47,6 +47,11 @@ export enum SkillKind { Support = 3 } +export enum BuffRunType { + Attr = 0, + Interval = 1 +} + /** * 攻击距离类型分类 * 用于AI决策和技能配置规范化 @@ -147,6 +152,8 @@ export interface BuffConf { chance:number; // 触发概率 info?:string; // 描述 isDebuff?:boolean; // 是否为负面效果 + runType?:BuffRunType; + interval?:number; } interface IReady { @@ -325,6 +332,8 @@ export const BuffsList: Record = { 10301: { uuid: 10301, name: "治疗", icon: "1292", buff: Attrs.hp, BType: BType.RATIO, value: 30, time: 0, chance: 1, info: "回复30%最大生命值" }, // 护盾 (基于攻击力百分比) 10302: { uuid: 10302, name: "护盾", icon: "1255", buff: Attrs.shield, BType: BType.RATIO, value: 30, time: 0, chance: 1, info: "获得30%最大生命值护盾" }, + 10311: { uuid: 10311, name: "持续治疗", icon: "1292", buff: Attrs.hp, BType: BType.RATIO, value: 5, time: 5, interval: 1, chance: 1, runType: BuffRunType.Interval, info: "每秒回复5%最大生命值,持续5秒" }, + 10312: { uuid: 10312, name: "流血", icon: "10211", buff: Attrs.hp, BType: BType.RATIO, value: -4, time: 5, interval: 1, chance: 1, isDebuff: true, runType: BuffRunType.Interval, info: "每秒损失4%最大生命值,持续5秒" }, // ========== 减益类 Buff (属性降低) ========== 10200 - 10299 // 减速 (移动速度降低) diff --git a/assets/script/game/hero/HeroAttrsComp.ts b/assets/script/game/hero/HeroAttrsComp.ts index 7dc0b7db..f958af07 100644 --- a/assets/script/game/hero/HeroAttrsComp.ts +++ b/assets/script/game/hero/HeroAttrsComp.ts @@ -2,7 +2,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { GameEvent } from "../common/config/GameEvent"; import { Attrs, BType } from "../common/config/HeroAttrs"; -import { BuffConf, SkillDisVal, SkillRange } from "../common/config/SkillSet"; +import { BuffConf, BuffRunType, SkillDisVal, SkillRange } from "../common/config/SkillSet"; import { HeroInfo, HType } from "../common/config/heroSet"; import { mLogger } from "../common/Logger"; import { smc } from "../common/SingletonModuleComp"; @@ -14,6 +14,24 @@ interface talTrigger{ value:number count:number } +interface ActiveBuffState { + id: number + attr: Attrs + sourceUuid: number + value: number + BType: BType + time: number +} +interface IntervalBuffState { + id: number + attr: Attrs + sourceUuid: number + value: number + BType: BType + interval: number + remain: number + tick: number +} @ecs.register('HeroAttrs') export class HeroAttrsComp extends ecs.Comp { public debugMode: boolean = true; @@ -77,8 +95,10 @@ export class HeroAttrsComp extends ecs.Comp { // ==================== Buff/Debuff 系统 ==================== /** 持久型buff数组 - 不会自动过期 */ - BUFFS: Record> = {}; - DEBUFFS: Record> = {}; + BUFFS: Record = {}; + DEBUFFS: Record = {}; + INTERVAL_EFFECTS: IntervalBuffState[] = []; + private buffInstanceId = 0; // ==================== 标记状态 ==================== is_dead: boolean = false; @@ -110,6 +130,8 @@ export class HeroAttrsComp extends ecs.Comp { // 清空现有 buff/debuff this.BUFFS = {}; this.DEBUFFS = {}; + this.INTERVAL_EFFECTS = []; + this.buffInstanceId = 0; // 获取英雄配置 const heroInfo = HeroInfo[this.hero_uuid]; if (!heroInfo) return; @@ -156,12 +178,24 @@ export class HeroAttrsComp extends ecs.Comp { * @param buffConf buff 配置 */ addBuff(buffConf: BuffConf) { - const applyType = buffConf.BType === BType.BOOLEAN ? BType.BOOLEAN : BType.VALUE; - const resolvedValue = applyType === BType.BOOLEAN - ? buffConf.value - : this.resolveBuffValue(buffConf.buff, buffConf.value, buffConf.BType); + const normalized = this.normalizeBuffValue(buffConf); + if (buffConf.runType === BuffRunType.Interval) { + const interval = buffConf.interval && buffConf.interval > 0 ? buffConf.interval : 1; + const remain = buffConf.time > 0 ? buffConf.time : interval; + this.INTERVAL_EFFECTS.push({ + id: ++this.buffInstanceId, + attr: buffConf.buff, + sourceUuid: buffConf.uuid, + value: normalized.value, + BType: normalized.BType, + interval, + remain, + tick: interval + }); + return; + } if (buffConf.time <= 0) { - this.applyAttrChange(buffConf.buff, resolvedValue, applyType); + this.applyAttrChange(buffConf.buff, normalized.value, normalized.BType); return; } @@ -173,14 +207,27 @@ export class HeroAttrsComp extends ecs.Comp { const currentBuffs = targetList[attrKey]; currentBuffs.push({ - value: resolvedValue, - BType: applyType, + id: ++this.buffInstanceId, + attr: buffConf.buff, + sourceUuid: buffConf.uuid, + value: normalized.value, + BType: normalized.BType, time: buffConf.time }); - this.applyAttrChange(buffConf.buff, resolvedValue, applyType); + this.applyAttrChange(buffConf.buff, normalized.value, normalized.BType); - mLogger.log(this.debugMode, 'HeroAttrs', `添加Buff: ${buffConf.name}, 属性:${buffConf.buff}, 值:${resolvedValue}, 时间:${buffConf.time}`); + mLogger.log(this.debugMode, 'HeroAttrs', `添加Buff: ${buffConf.name}, 属性:${buffConf.buff}, 值:${normalized.value}, 时间:${buffConf.time}`); + } + + private normalizeBuffValue(buffConf: BuffConf): { value: number; BType: BType } { + if (buffConf.BType === BType.BOOLEAN) { + return { value: buffConf.value, BType: BType.BOOLEAN }; + } + return { + value: this.resolveBuffValue(buffConf.buff, buffConf.value, buffConf.BType), + BType: BType.VALUE + }; } private resolveBuffValue(attr: Attrs, value: number, type: BType): number { @@ -286,7 +333,34 @@ export class HeroAttrsComp extends ecs.Comp { this.updateStatusFlags(); } - private updateList(list: Record>, dt: number) { + updateIntervalEffectsBySystem(dt: number) { + for (let i = this.INTERVAL_EFFECTS.length - 1; i >= 0; i--) { + const state = this.INTERVAL_EFFECTS[i]; + state.remain -= dt; + state.tick -= dt; + while (state.tick <= 0 && state.remain > 0) { + this.applyIntervalEffect(state); + state.tick += state.interval; + } + if (state.remain <= 0) { + this.INTERVAL_EFFECTS.splice(i, 1); + } + } + } + + private applyIntervalEffect(state: IntervalBuffState) { + if (state.attr === Attrs.hp) { + this.add_hp(state.value, true); + return; + } + if (state.attr === Attrs.shield) { + this.add_shield(state.value, true); + return; + } + this.applyAttrChange(state.attr, state.value, state.BType); + } + + private updateList(list: Record, dt: number) { for (const attrKey in list) { const buffs = list[attrKey]; if (!buffs || buffs.length === 0) continue; @@ -297,14 +371,10 @@ export class HeroAttrsComp extends ecs.Comp { buff.time -= dt; if (buff.time <= 0) { - // Buff 过期,移除属性加成 - // 注意:key 是 string (from record key),需要转为 Attrs - const attrName = attrKey as unknown as Attrs; - this.applyAttrChange(attrName, buff.value, buff.BType, true); // reverse = true + this.applyAttrChange(buff.attr, buff.value, buff.BType, true); - // 从列表中移除 buffs.splice(i, 1); - mLogger.log(this.debugMode, 'HeroAttrs', `Buff过期: 属性:${attrName}, 恢复值:${buff.value}`); + mLogger.log(this.debugMode, 'HeroAttrs', `Buff过期: 属性:${buff.attr}, 恢复值:${buff.value}`); } } @@ -421,6 +491,8 @@ export class HeroAttrsComp extends ecs.Comp { this.BUFFS = {}; this.DEBUFFS = {}; + this.INTERVAL_EFFECTS = []; + this.buffInstanceId = 0; // 重置技能距离缓存 this.maxSkillDistance = 0; this.minSkillDistance = 0; @@ -463,6 +535,7 @@ export class HeroBuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpd const attrs = e.get(HeroAttrsComp); if (!attrs || attrs.is_dead) return; attrs.updateBuffsDebuffs(this.dt); + attrs.updateIntervalEffectsBySystem(this.dt); } }