feat(buff): 新增间隔触发型buff效果支持

- 在 SkillSet.ts 中添加 BuffRunType 枚举和 interval 配置字段
- 在 HeroAttrsComp 中实现间隔效果处理逻辑,支持持续治疗和流血等效果
- 新增 INTERVAL_EFFECTS 数组和 updateIntervalEffectsBySystem 方法来管理间隔触发
- 添加 10311(持续治疗)和 10312(流血)两个示例buff配置
This commit is contained in:
panw
2026-03-13 10:21:40 +08:00
parent 3b545e3bff
commit d2418c03c8
2 changed files with 101 additions and 19 deletions

View File

@@ -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<number, BuffConf> = {
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
// 减速 (移动速度降低)

View File

@@ -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<number, Array<{value: number, BType: BType,time:number}>> = {};
DEBUFFS: Record<number, Array<{value: number, BType: BType,time:number}>> = {};
BUFFS: Record<number, ActiveBuffState[]> = {};
DEBUFFS: Record<number, ActiveBuffState[]> = {};
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<number, Array<{value: number, BType: BType, time: number}>>, 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<number, ActiveBuffState[]>, 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);
}
}