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 Support = 3
} }
export enum BuffRunType {
Attr = 0,
Interval = 1
}
/** /**
* 攻击距离类型分类 * 攻击距离类型分类
* 用于AI决策和技能配置规范化 * 用于AI决策和技能配置规范化
@@ -147,6 +152,8 @@ export interface BuffConf {
chance:number; // 触发概率 chance:number; // 触发概率
info?:string; // 描述 info?:string; // 描述
isDebuff?:boolean; // 是否为负面效果 isDebuff?:boolean; // 是否为负面效果
runType?:BuffRunType;
interval?:number;
} }
interface IReady { 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%最大生命值" }, 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%最大生命值护盾" }, 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 // ========== 减益类 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 { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent"; import { GameEvent } from "../common/config/GameEvent";
import { Attrs, BType } from "../common/config/HeroAttrs"; 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 { HeroInfo, HType } from "../common/config/heroSet";
import { mLogger } from "../common/Logger"; import { mLogger } from "../common/Logger";
import { smc } from "../common/SingletonModuleComp"; import { smc } from "../common/SingletonModuleComp";
@@ -14,6 +14,24 @@ interface talTrigger{
value:number value:number
count: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') @ecs.register('HeroAttrs')
export class HeroAttrsComp extends ecs.Comp { export class HeroAttrsComp extends ecs.Comp {
public debugMode: boolean = true; public debugMode: boolean = true;
@@ -77,8 +95,10 @@ export class HeroAttrsComp extends ecs.Comp {
// ==================== Buff/Debuff 系统 ==================== // ==================== Buff/Debuff 系统 ====================
/** 持久型buff数组 - 不会自动过期 */ /** 持久型buff数组 - 不会自动过期 */
BUFFS: Record<number, Array<{value: number, BType: BType,time:number}>> = {}; BUFFS: Record<number, ActiveBuffState[]> = {};
DEBUFFS: Record<number, Array<{value: number, BType: BType,time:number}>> = {}; DEBUFFS: Record<number, ActiveBuffState[]> = {};
INTERVAL_EFFECTS: IntervalBuffState[] = [];
private buffInstanceId = 0;
// ==================== 标记状态 ==================== // ==================== 标记状态 ====================
is_dead: boolean = false; is_dead: boolean = false;
@@ -110,6 +130,8 @@ export class HeroAttrsComp extends ecs.Comp {
// 清空现有 buff/debuff // 清空现有 buff/debuff
this.BUFFS = {}; this.BUFFS = {};
this.DEBUFFS = {}; this.DEBUFFS = {};
this.INTERVAL_EFFECTS = [];
this.buffInstanceId = 0;
// 获取英雄配置 // 获取英雄配置
const heroInfo = HeroInfo[this.hero_uuid]; const heroInfo = HeroInfo[this.hero_uuid];
if (!heroInfo) return; if (!heroInfo) return;
@@ -156,12 +178,24 @@ export class HeroAttrsComp extends ecs.Comp {
* @param buffConf buff 配置 * @param buffConf buff 配置
*/ */
addBuff(buffConf: BuffConf) { addBuff(buffConf: BuffConf) {
const applyType = buffConf.BType === BType.BOOLEAN ? BType.BOOLEAN : BType.VALUE; const normalized = this.normalizeBuffValue(buffConf);
const resolvedValue = applyType === BType.BOOLEAN if (buffConf.runType === BuffRunType.Interval) {
? buffConf.value const interval = buffConf.interval && buffConf.interval > 0 ? buffConf.interval : 1;
: this.resolveBuffValue(buffConf.buff, buffConf.value, buffConf.BType); 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) { if (buffConf.time <= 0) {
this.applyAttrChange(buffConf.buff, resolvedValue, applyType); this.applyAttrChange(buffConf.buff, normalized.value, normalized.BType);
return; return;
} }
@@ -173,14 +207,27 @@ export class HeroAttrsComp extends ecs.Comp {
const currentBuffs = targetList[attrKey]; const currentBuffs = targetList[attrKey];
currentBuffs.push({ currentBuffs.push({
value: resolvedValue, id: ++this.buffInstanceId,
BType: applyType, attr: buffConf.buff,
sourceUuid: buffConf.uuid,
value: normalized.value,
BType: normalized.BType,
time: buffConf.time 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 { private resolveBuffValue(attr: Attrs, value: number, type: BType): number {
@@ -286,7 +333,34 @@ export class HeroAttrsComp extends ecs.Comp {
this.updateStatusFlags(); 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) { for (const attrKey in list) {
const buffs = list[attrKey]; const buffs = list[attrKey];
if (!buffs || buffs.length === 0) continue; if (!buffs || buffs.length === 0) continue;
@@ -297,14 +371,10 @@ export class HeroAttrsComp extends ecs.Comp {
buff.time -= dt; buff.time -= dt;
if (buff.time <= 0) { if (buff.time <= 0) {
// Buff 过期,移除属性加成 this.applyAttrChange(buff.attr, buff.value, buff.BType, true);
// 注意key 是 string (from record key),需要转为 Attrs
const attrName = attrKey as unknown as Attrs;
this.applyAttrChange(attrName, buff.value, buff.BType, true); // reverse = true
// 从列表中移除
buffs.splice(i, 1); 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.BUFFS = {};
this.DEBUFFS = {}; this.DEBUFFS = {};
this.INTERVAL_EFFECTS = [];
this.buffInstanceId = 0;
// 重置技能距离缓存 // 重置技能距离缓存
this.maxSkillDistance = 0; this.maxSkillDistance = 0;
this.minSkillDistance = 0; this.minSkillDistance = 0;
@@ -463,6 +535,7 @@ export class HeroBuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
const attrs = e.get(HeroAttrsComp); const attrs = e.get(HeroAttrsComp);
if (!attrs || attrs.is_dead) return; if (!attrs || attrs.is_dead) return;
attrs.updateBuffsDebuffs(this.dt); attrs.updateBuffsDebuffs(this.dt);
attrs.updateIntervalEffectsBySystem(this.dt);
} }
} }