№ · BUFF 系统 CH.06.24
主页 · ⚡ Buff 系统 · 《同福客栈》Buff 体系具体配置清单与实装细则

《同福客栈》Buff 体系具体配置清单与实装细则

📅 2026-06-24 · 📦 6.5 KB · ⚡ Buff 系统 · 📝 MD 文档 🏷️ 员工🏷️ Buff🏷️ 设计🏷️ 终局

在上一份《Buff系统实装与落地指南》的框架指导下,本文档提供具体的代码级实装细节第一批需要落地的 Buff 配置清单,供开发人员直接拷贝或参考,以快速在代码库(如 src/App.tsx 和相关数据文件)中完成集成。


1. 第一批核心 Buff 配置清单 (JSON / TS 配置表)

建议在 src/data/buffConfigs.ts 中统一定义静态配置。以下是根据游戏策划文档提炼的首批核心 Buff:

import { BuffConfig } from '../types/BuffTypes';

export const BUFF_CONFIGS: Record<string, BuffConfig> = {
  // ----------------- 营业状态类 -----------------
  PEAK_HOUR: {
    id: 'PEAK_HOUR',
    name: '高峰营业',
    desc: '饭点时段客流量爆满,营收增加,但损耗加剧。',
    icon: '🔥',
    isDebuff: false,
    effects: [
      { attribute: 'customerFlowLimit', modifierType: 'MULTIPLY', value: 1.5 },
      { attribute: 'revenueRate', modifierType: 'MULTIPLY', value: 1.5 },
      { attribute: 'cleanlinessDecay', modifierType: 'MULTIPLY', value: 1.4 }
    ]
  },
  POOR_HYGIENE_SUSPEND: {
    id: 'POOR_HYGIENE_SUSPEND',
    name: '临时卫生整顿',
    desc: '环境脏乱差,被衙门勒令停业整改。',
    icon: '🧹',
    isDebuff: true,
    effects: [
      { attribute: 'businessState', modifierType: 'OVERRIDE', value: 'SUSPENDED' },
      { attribute: 'revenueRate', modifierType: 'OVERRIDE', value: 0 }
    ]
  },

  // ----------------- 势力合璧类 -----------------
  FACTION_COMBO_MERCHANT: {
    id: 'FACTION_COMBO_MERCHANT',
    name: '官商一体',
    desc: '衙门与乡绅好感双双达标,成为官方指定驿站。',
    icon: '🤝',
    isDebuff: false,
    effects: [
      { attribute: 'vipOrderChance', modifierType: 'ADD', value: 0.3 } // 贵客订单概率 +30%
    ]
  },

  // ----------------- 员工状态类 -----------------
  ANGRY_STRIKE: {
    id: 'ANGRY_STRIKE',
    name: '消极怠工',
    desc: '员工心情极差,干活磨洋工。',
    icon: '💢',
    isDebuff: true,
    effects: [
      { attribute: 'serviceSpeed', modifierType: 'MULTIPLY', value: 0.7 } // 出餐/上菜速度 -30%
    ]
  }
};

2. BuffEngine 核心类实装代码

src/utils/BuffEngine.ts 中实现核心数值拦截逻辑:

import { ActiveBuff, ModifierType } from '../types/BuffTypes';
import { BUFF_CONFIGS } from '../data/buffConfigs';

export class BuffEngine {
  private activeBuffs: ActiveBuff[] = [];

  constructor(initialBuffs: ActiveBuff[] = []) {
    this.activeBuffs = initialBuffs;
  }

  // 注入或更新当前的 Buff 列表(由状态管理器调用)
  public setActiveBuffs(buffs: ActiveBuff[]) {
    this.activeBuffs = buffs;
  }

  // 核心拦截计算器
  public calculateFinalValue(attribute: string, baseValue: number, targetId?: string): number | string {
    let finalValue: any = baseValue;
    let multiplier = 1.0;

    // 收集所有生效且匹配该属性的 effect
    const relevantEffects = this.activeBuffs.flatMap(active => {
      const config = BUFF_CONFIGS[active.buffId];
      if (!config) return [];
      return config.effects.filter(effect => 
        effect.attribute === attribute && 
        (!effect.targetId || effect.targetId === targetId)
      );
    });

    if (relevantEffects.length === 0) return finalValue;

    // 1. OVERRIDE 覆盖优先级最高(如果有多个,取最新的)
    const overrideEffect = relevantEffects.reverse().find(e => e.modifierType === 'OVERRIDE');
    if (overrideEffect) return overrideEffect.value;

    // 2. ADD 固定值加减
    relevantEffects.filter(e => e.modifierType === 'ADD').forEach(e => {
      finalValue += e.value;
    });

    // 3. MULTIPLY 百分比乘区加法运算 (如 1.5 和 1.2 叠加 = 1 + 0.5 + 0.2 = 1.7)
    relevantEffects.filter(e => e.modifierType === 'MULTIPLY').forEach(e => {
      multiplier += (e.value - 1);
    });

    return finalValue * multiplier;
  }
}

// 导出单例供全局调用
export const buffEngine = new BuffEngine();

3. 在主循环 (Game Tick) 中的植入

假设主逻辑在 src/App.tsx 或某个核心 Hook (useGameLoop) 中:

import { buffEngine } from './utils/BuffEngine';

// 1. 每次 Tick 更新 Buff 时长
const tickBuffs = (deltaMs: number) => {
  setActiveBuffs(prevBuffs => {
    let changed = false;
    const nextBuffs = prevBuffs.filter(buff => {
      if (buff.duration === undefined) return true; // 永久或条件 Buff
      
      buff.duration -= deltaMs;
      if (buff.duration <= 0) {
        changed = true;
        // 可以触发一个事件通知 UI "Buff 已结束"
        return false; 
      }
      return true;
    });
    
    if (changed) buffEngine.setActiveBuffs(nextBuffs);
    return nextBuffs;
  });
};

// 2. 数值拦截替换 (替换原有硬编码)
const calculateDailyRevenue = () => {
  const BASE_FLOW = 50;
  // 拦截计算:客流上限
  const finalFlow = buffEngine.calculateFinalValue('customerFlowLimit', BASE_FLOW);
  
  const BASE_REVENUE_RATE = 1.0;
  // 拦截计算:营收倍率
  const finalRevenueRate = buffEngine.calculateFinalValue('revenueRate', BASE_REVENUE_RATE);

  return finalFlow * 20 * finalRevenueRate; // 假设每人消费20铜钱
};

4. 条件触发类 Buff 的监听植入 (事件驱动)

对于【官商一体】这种不依赖时长,而是依赖势力好感度的 Buff,建议在“好感度变动”的统一回调中检测:

const onFactionFavorabilityChanged = (factionState: FactionState) => {
  // 检查是否满足“官商一体”
  const hasMerchantCombo = factionState.yamen >= 80 && factionState.gentry >= 80;
  
  setActiveBuffs(prev => {
    const exists = prev.some(b => b.buffId === 'FACTION_COMBO_MERCHANT');
    
    if (hasMerchantCombo && !exists) {
      // 满足条件且未添加,注入该 Buff
      return [...prev, { buffId: 'FACTION_COMBO_MERCHANT', startTime: Date.now(), source: 'FACTION' }];
    } else if (!hasMerchantCombo && exists) {
      // 条件不满足但已存在,移除该 Buff
      return prev.filter(b => b.buffId !== 'FACTION_COMBO_MERCHANT');
    }
    return prev;
  });
};

5. 总结与下一步

这套实装细则可以直接运用于目前的 React 前端架构中。第一步请优先将 BuffEngine.ts 类封装完毕,第二步将现有的核心结算代码(客流量、金币增减)用 calculateFinalValue 包裹,最后在 UI 上渲染 activeBuffs 即可。