# BuffManager **Repository Path**: yuzu-46/buff-manager ## Basic Information - **Project Name**: BuffManager - **Description**: Buff管理器 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-22 - **Last Updated**: 2026-01-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Buff Manager 游戏增益/减益效果管理系统。 ## 项目简介 Buff Manager 是一个用于管理游戏中增益/减益效果(Buffs/Debuffs)的系统。它提供了完整的 Buff 生命周期管理,包括添加、移除、刷新、堆叠等功能,并支持冲突组机制,适用于游戏开发中的角色状态管理。 ## 功能特性 - **完整的Buff生命周期管理** - 添加、移除、刷新、过期 - **冲突组机制** - 防止冲突的 Buff 同时生效 - **时间缩放支持** - 支持慢动作、加速等效果 - **高精度时间处理** - 在高频更新场景下使用高精度时间API,确保时间准确性 - **状态一致性保证** - 在处理冲突组时,确保新Buff成功创建后再移除旧Buff ## API 该API提供了一套完整的方法来管理游戏中的增益/减益效果,包括注册模板、添加/移除Buff、查询状态等功能。API主要分为三类:类、类型定义和枚举。 ### 类 #### BuffManager Buff 管理器类,负责管理所有 Buff 实例的生命周期。 ##### registerTemplate(template: BuffTemplate): void 注册一个 Buff 类型模板,定义 Buff 的基础属性和行为。 - 参数: - template: [BuffTemplate](#bufftemplate) - 要注册的 Buff 模板对象 ##### addBuff(containerId: ContainerId, typeId: BuffTypeId): BuffInfo | null 向指定容器添加一个 Buff。 - 参数: - containerId: [ContainerId](#containerid) - 容器唯一标识符(如玩家ID) - typeId: [BuffTypeId](#bufftypeid) - 要添加的 Buff 类型ID - 返回值:[BuffInfo](#buffinfo) \| null - 成功时返回 Buff 信息对象,失败时返回 null ##### removeBuff(buffId: BuffId, reason: RemoveReason = RemoveReason.Manual): boolean 移除指定 ID 的 Buff。 - 参数: - buffId: [BuffId](#buffid) - 要移除的 Buff 实例ID - reason: [RemoveReason](#removereason) (可选) - 移除原因,默认为 Manual - 返回值:boolean - 成功移除返回 true,找不到对应 Buff 返回 false ##### removeBuffsByTemplate(containerId: ContainerId, typeId: BuffTypeId): void 移除容器上所有指定类型的 Buff。 - 参数: - containerId: [ContainerId](#containerid) - 容器唯一标识符 - typeId: [BuffTypeId](#bufftypeid) - 要移除的 Buff 类型ID ##### clearContainer(containerId: ContainerId, reason: RemoveReason = RemoveReason.Manual): void 清空指定容器的所有 Buff(如玩家登出时使用)。 - 参数: - containerId: [ContainerId](#containerid) - 要清空的容器ID ##### getBuffs(containerId: ContainerId): BuffInfo[] 获取容器上的所有 Buff 只读信息。 - 参数: - containerId: [ContainerId](#containerid) - 容器唯一标识符 - 返回值:[BuffInfo](#buffinfo)[] - 该容器上所有 Buff 的只读信息数组 ##### hasBuff(containerId: ContainerId, typeId: BuffTypeId): boolean 检查容器是否拥有指定类型的 Buff。 - 参数: - containerId: [ContainerId](#containerid) - 容器唯一标识符 - typeId: [BuffTypeId](#bufftypeid) - 要检查的 Buff 类型ID - 返回值:boolean - 如果容器拥有该类型 Buff 返回 true,否则返回 false ##### getTotalStacks(containerId: ContainerId, typeIds: BuffTypeId[]): number 获取容器上某些类型 Buff 的总层数。 - 参数: - containerId: [ContainerId](#containerid) - 容器唯一标识符 - typeIds: [BuffTypeId](#bufftypeid)[] - 要统计的 Buff 类型ID数组 - 返回值:number - 这些类型 Buff 的总层数 ##### enableAutoUpdate(): void 启用自动更新(使用固定时间步长),使 Buff 能够自动更新和过期。 - 参数:无 ##### disableAutoUpdate(): void 禁用自动更新。 - 参数:无 ##### setTimeScale(scale: number): void 设置时间缩放(用于慢动作、加速等效果)。 - 参数: - scale: number - 时间缩放比例,1.0为正常速度,小于1.0为减速,大于1.0为加速 ### 类型定义 | 类型 | 描述 | | ------------- | -------------------------------------------- | | `ContainerId` | 容器唯一标识符(如玩家、怪物等),字符串类型 | | `BuffId` | Buff 实例唯一标识符,字符串类型 | | `BuffTypeId` | Buff 类型(模板)唯一标识符,字符串类型 | | 接口 | 描述 | | -------------- | ------------------------- | | `BuffTemplate` | Buff 类型模板(静态配置) | | `BuffInfo` | Buff 只读视图 | | `BuffEvents` | Buff 生命周期事件回调接口 | #### BuffTemplate Buff 类型模板(静态配置),包含以下字段: | 字段 | 类型 | 描述 | | ----------------- | ------------ | --------------------------------------------------- | | `id` | `string` | 唯一类型 ID | | `name` | `string` | 显示名称 | | `duration` | `number` | 持续时间(毫秒),0 表示永久 | | `tickInterval` | `number` | Tick 间隔(毫秒),0 表示每帧触发 | | `conflictGroups?` | `string[]` | 冲突组列表。同一容器内,所排斥的 Buff,会自动被移除 | | `events?` | `BuffEvents` | 生命周期事件 | #### BuffInfo Buff 只读视图,包含以下字段: | 字段 | 类型 | 描述 | | -------------- | ------------- | -------------------- | | `id` | `BuffId` | Buff 实例唯一 ID | | `containerId` | `ContainerId` | 所属容器 ID | | `templateId` | `BuffTypeId` | Buff 类型 ID | | `durationLeft` | `number` | 剩余持续时间(毫秒) | #### BuffEvents Buff 生命周期事件回调接口,包含以下可选方法: | 方法 | 签名 | 描述 | | ---------- | ----------------------------------------- | --------------------- | | `onApply` | `(buffInfo, containerId) => void` | Buff 被应用时触发 | | `onTick` | `(buffInfo, containerId) => void` | Buff 周期性触发时调用 | | `onRemove` | `(buffInfo, containerId, reason) => void` | Buff 被移除时触发 | ### 枚举 #### RemoveReason 枚举类型,表示 Buff 被移除的原因: | 值 | 描述 | | ------------- | ---------------- | | `Expired` | 持续时间自然结束 | | `Dispel` | 被驱散技能移除 | | `Overwritten` | 被新 Buff 覆盖 | | `Manual` | 主动手动移除 | ## API 使用示例 ### 示例效果 https://dao3.fun/exp/experience/detail/100545262 ### 示例代码 以下是两种不同环境下的使用示例,展示了如何注册Buff模板、添加Buff以及管理Buff的生命周期。 #### TypeScript + ES6 Modules 示例 ```typescript /** * example * ArenaPro 示例 */ // 需按照实际情况导入 import type { BuffTemplate } from 'buff-manager'; import { buffManager, RemoveReason } from 'buff-manager'; // 定义一个加速Buff模板 const speedUpTemplate: BuffTemplate = { id: 'speed-up', name: 'Speed Boost', duration: 5000, // 持续 5 秒 tickInterval: 1000, // 每秒触发一次 events: { // 应用时触发 onApply: (buffInfo, containerId) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.runSpeed += 0.1; playerEntity.player.directMessage(`你获得了加速效果!`); } } }, // 每次触发时触发 onTick: (buffInfo, containerId) => { console.log( `${containerId}的加速效果持续中,剩余时间: ${buffInfo.durationLeft}ms` ); }, // 移除时触发 onRemove: (buffInfo, containerId, reason) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.runSpeed -= 0.1; playerEntity.player.directMessage(`你失去了加速效果!`); } } }, }, }; // 定义一个伤害Buff模板(Debuff) const damageOverTimeTemplate: BuffTemplate = { id: 'damage-over-time', name: 'Poison Damage', duration: 10000, // 持续 10 秒 tickInterval: 1000, // 每1秒触发一次 conflictGroups: ['speed-up'], // 与加速Buff冲突,添加当前buff时会移除速度效果 events: { onApply: (buffInfo, containerId) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.directMessage(`你获得了伤害效果!`); } } }, onTick: (buffInfo, containerId) => { // 模拟每tick造成伤害 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.enableDamage = true; playerEntity.hurt(1); playerEntity.player.directMessage(`你被伤害了!`); } }, onRemove: (buffInfo, containerId, reason) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.directMessage(`你失去了伤害效果!`); } } }, }, }; // 注册Buff模板 buffManager.registerTemplate(speedUpTemplate); buffManager.registerTemplate(damageOverTimeTemplate); // 启用自动更新,使Buff能够自动计时和过期 buffManager.enableAutoUpdate(); // 监听玩家加入事件,给玩家添加加速效果 world.onPlayerJoin(({ entity }) => { buffManager.addBuff(`player-${entity.player.userId}`, 'speed-up'); }); // 监听玩家离开事件,移除玩家所有Buff world.onPlayerLeave(({ entity }) => { buffManager.clearContainer(`player-${entity.player.userId}`); }); // 监听玩家聊天事件,给玩家添加伤害效果 world.onChat(({ entity }) => { if (entity.player) { buffManager.addBuff( `player-${entity.player.userId}`, 'damage-over-time' ); } }); ``` #### JavaScript + CommonJS 示例 ```javascript /** * example * Arena 示例 */ // 需按照实际情况导入 const { buffManager, RemoveReason } = require('buff-manager'); // 定义一个加速Buff模板 const speedUpTemplate = { id: 'speed-up', name: 'Speed Boost', duration: 5000, // 持续 5 秒 tickInterval: 1000, // 每秒触发一次 events: { // 应用时触发 onApply: (buffInfo, containerId) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.runSpeed += 0.1; playerEntity.player.directMessage(`你获得了加速效果!`); } } }, // 每次触发时触发 onTick: (buffInfo, containerId) => { console.log( `${containerId}的加速效果持续中,剩余时间: ${buffInfo.durationLeft}ms` ); }, // 移除时触发 onRemove: (buffInfo, containerId, reason) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.runSpeed -= 0.1; playerEntity.player.directMessage(`你失去了加速效果!`); } } }, }, }; // 定义一个伤害Buff模板(Debuff) const damageOverTimeTemplate = { id: 'damage-over-time', name: 'Poison Damage', duration: 10000, // 持续 10 秒 tickInterval: 1000, // 每1秒触发一次 conflictGroups: ['speed-up'], // 与加速Buff冲突,添加当前buff时会移除速度效果 events: { onApply: (buffInfo, containerId) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.directMessage(`你获得了伤害效果!`); } } }, onTick: (buffInfo, containerId) => { // 模拟每tick造成伤害 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.enableDamage = true; playerEntity.hurt(1); playerEntity.player.directMessage(`你被伤害了!`); } }, onRemove: (buffInfo, containerId, reason) => { if (buffInfo.containerId.startsWith('player-')) { // 获取玩家实体 const playerEntity = world .querySelectorAll('player') .find( (entity) => `player-${entity.player.userId}` === containerId ); if (playerEntity) { playerEntity.player.directMessage(`你失去了伤害效果!`); } } }, }, }; // 注册Buff模板 buffManager.registerTemplate(speedUpTemplate); buffManager.registerTemplate(damageOverTimeTemplate); // 启用自动更新,使Buff能够自动计时和过期 buffManager.enableAutoUpdate(); // 监听玩家加入事件,给玩家添加加速效果 world.onPlayerJoin(({ entity }) => { buffManager.addBuff(`player-${entity.player.userId}`, 'speed-up'); }); // 监听玩家离开事件,移除玩家所有Buff world.onPlayerLeave(({ entity }) => { buffManager.clearContainer(`player-${entity.player.userId}`); }); // 监听玩家聊天事件,给玩家添加伤害效果 world.onChat(({ entity }) => { if (entity.player) { buffManager.addBuff( `player-${entity.player.userId}`, 'damage-over-time' ); } }); ``` ## 注意事项 - 在处理Buff相关参数时,请确保duration等参数的有效性,防止非法值导致异常 - 当处理冲突组时,系统会在新Buff成功创建后再移除旧Buff,以确保状态一致性 - 使用enableAutoUpdate()时,系统会自动管理Buff的生命周期,但请注意及时调用disableAutoUpdate()以避免内存泄漏 - 高频更新场景下,系统使用高精度时间API确保时间计算的准确性 ## 技术栈 - **语言**: TypeScript - **构建工具**: Vite ## 贡献者 - 柚子46 (Yuzu-46) ## 许可证 [MIT License](./LICENSE)