feat(buff): 新增间隔触发型buff效果支持
- 在 SkillSet.ts 中添加 BuffRunType 枚举和 interval 配置字段 - 在 HeroAttrsComp 中实现间隔效果处理逻辑,支持持续治疗和流血等效果 - 新增 INTERVAL_EFFECTS 数组和 updateIntervalEffectsBySystem 方法来管理间隔触发 - 添加 10311(持续治疗)和 10312(流血)两个示例buff配置
This commit is contained in:
@@ -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
|
||||
// 减速 (移动速度降低)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user