№ · BUFF 系统
CH.06.24
《同福客栈》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 即可。