№ · 技术设计
CH.06.25
《同福客栈》账号天赋与传承系统技术文档
1. 文档概述
本文档定义账号天赋系统与传承道具系统的数据结构、接口规范和实现方案。基于现有Buff系统和道具系统进行扩展。
1.1 技术栈
- 前端框架:React + TypeScript
- 状态管理:Zustand
- 存储方案:LocalStorage(无服务器架构)
1.2 依赖系统
- Buff系统(RuntimeBuff结构)
- 道具系统(GameItem, BaggageItem)
- 成就系统(GlobalProfile)
- 存档系统(PlaythroughSaveSlot)
2. 数据结构定义
2.1 天赋配置接口(静态配置表)
/**
* 天赋系统 - 静态配置表接口
* 存储位置:configs/talents.json(只读静态资源)
*/
// 天赋分支枚举
export type TalentBranch = 'BUSINESS' | 'JIANGHU' | 'MYSTIC';
// 天赋作用目标类型
export type TalentTargetType = 'INN' | 'STAFF' | 'GLOBAL';
// 天赋配置接口
export interface StaticTalentConfig {
id: string; // 天赋唯一ID (如: TALENT_BUSINESS_01)
name: string; // 天赋名称 (如: 佟家祖训)
desc: string; // 天赋描述
branch: TalentBranch; // 所属分支
tier: number; // 天赋层级 (1-4,用于解锁前置)
cost: number; // 消耗天赋点
prerequisiteId?: string; // 前置天赋ID(可选)
icon: string; // 图标路径
// 生成的Buff配置
buffConfig: {
configId: string; // Buff配置ID (如: BUFF_TALENT_BUSINESS_01)
targetType: TalentTargetType; // 作用目标类型
targetId?: string; // 作用目标ID(如员工ID 'bai',INN类型时为空)
tags: string[]; // Buff标签
duration: number; // 持续时间 (-1为永久,周目内有效)
modifiers: BuffModifier[]; // 属性修饰器列表
};
unlockCondition?: { // 解锁条件(可选,部分天赋有额外条件)
type: 'REPUTATION' | 'ACHIEVEMENT' | 'PLAYTHROUGH_COUNT';
value: number | string; // 条件值
};
sortOrder: number; // 排序权重
}
// Buff修饰器接口(复用现有结构)
export interface BuffModifier {
targetAttribute: string; // 目标属性
calcType: 'ADD' | 'MULTIPLY' | 'SET'; // 计算类型
value: number; // 数值
}
2.2 传承道具接口(扩展自GameItem)
/**
* 传承道具系统 - 扩展数据结构
* 基于现有 ItemCategory = 'LEGACY' 扩展
*/
// 传承道具子类型
export type LegacyItemSubType =
| 'CURRENCY_PACK' // 货币包(铜钱/银票)
| 'CONSUMABLE' // 跨周目消耗品(稀有食材、药材)
| 'EQUIPMENT' // 可传承装备
| 'TOKEN' // 信物/凭证(解锁剧情或NPC)
| 'BLUEPRINT'; // 图纸(解锁建筑/设施)
// 传承道具接口(扩展自GameItem)
export interface LegacyItemConfig {
id: string; // 道具唯一ID (如: LEGACY_CURRENCY_500)
name: string; // 道具名称
desc: string; // 道具描述
category: 'LEGACY'; // 固定为LEGACY
subType: LegacyItemSubType; // 传承道具子类型
rarity: 'RARE' | 'EPIC' | 'LEGENDARY'; // 稀有度(传承道具最低RARE)
icon: string; // 图标路径
flavorText: string; // 风味文本
// 传承特性
isPermanent: boolean; // 是否永久保留(true=不会被消耗)
maxHeld: number; // 最大持有数量
// 效果定义(周目开始时生效)
effects: LegacyItemEffect[];
// 获取来源
acquisitionSource: 'ACHIEVEMENT' | 'LEGACY_SHOP' | 'SPECIAL_EVENT';
acquisitionId?: string; // 来源ID(成就ID或商店商品ID)
// UI相关
sortOrder: number; // 排序权重
}
// 传承道具效果接口
export interface LegacyItemEffect {
type: 'STARTUP_CURRENCY' | // 开局货币
'STARTUP_BUFF' | // 开局Buff(生成RuntimeBuff)
'UNLOCK_NPC' | // 解锁特殊NPC
'UNLOCK_FACILITY' | // 解锁设施
'UNLOCK_RECIPE' | // 解锁菜谱
'LEGACY_SLOT' | // 增加传承槽位
'UNLOCK_TALENT_BRANCH'; // 解锁天赋分支
value?: number; // 数值效果
buffConfigId?: string; // 关联的Buff配置ID(STARTUP_BUFF类型时使用)
unlockId?: string; // 解锁目标ID
}
2.3 GlobalProfile扩展
/**
* GlobalProfile 扩展 - 账号天赋与传承道具
* 基于现有 GlobalProfile 接口扩展
*/
// 名望等级枚举
export type ReputationLevel =
| 'UNKNOWN' // 默默无闻 (0-99)
| 'FAMOUS' // 小有名气 (100-499)
| 'RENOWNED' // 声名远扬 (500-1499)
| 'LEGENDARY' // 威震江湖 (1500-4999)
| 'MYTHICAL'; // 传说永存 (5000+)
// 名望等级配置
export const REPUTATION_LEVEL_CONFIG: Record<ReputationLevel, {
min: number;
max: number;
title: string;
legacySlots: number;
maxTalentTier: number;
}> = {
UNKNOWN: { min: 0, max: 99, title: '新掌柜', legacySlots: 1, maxTalentTier: 2 },
FAMOUS: { min: 100, max: 499, title: '七侠镇掌柜', legacySlots: 2, maxTalentTier: 3 },
RENOWNED: { min: 500, max: 1499, title: '关中名店', legacySlots: 3, maxTalentTier: 4 },
LEGENDARY: { min: 1500, max: 4999, title: '天下第一楼', legacySlots: 4, maxTalentTier: 4 },
MYTHICAL: { min: 5000, max: Infinity, title: '同福传奇', legacySlots: 5, maxTalentTier: 4 }
};
// 传承道具库存接口
export interface LegacyItemInventory {
itemId: string; // 传承道具ID
quantity: number; // 持有数量
acquiredAt: number; // 获取时间戳
source: string; // 获取来源
}
// 周目印记接口
export interface PlaythroughStamp {
playthroughId: number; // 周目序号
outcome: PlaythroughOutcome; // 结局类型
survivalDays: number; // 存活天数
maxReputation: number; // 最高声望
totalSilverEarned: number; // 赚取银两
achievementsUnlocked: string[]; // 本局解锁成就
talentPointsEarned: number; // 本局获得天赋点
specialFlags: string[]; // 特殊标记
timestamp: number; // 结算时间戳
}
// 周目结局类型
export type PlaythroughOutcome =
| 'SUCCESS' // 通关(存活30天+)
| 'BANKRUPTCY' // 破产
| 'SHUTDOWN' // 被查封
| 'SPECIAL'; // 特殊结局
// 扩展的GlobalProfile接口
export interface GlobalProfileExtended {
// ========== 现有字段 ==========
legacyPoints: number; // 江湖阅历
unlockedAchievements: string[]; // 已解锁成就
globalCounters: Record<string, number>; // 全局计数器
purchasedLegacies: string[]; // 已购买传承商品
lastSavedAt: number;
signature: string;
// ========== 新增:江湖名望 ==========
accountReputation: number; // 账号名望值
reputationLevel: ReputationLevel; // 名望等级
// ========== 新增:天赋系统 ==========
talentPoints: number; // 当前可用天赋点
totalTalentPointsEarned: number; // 历史累计获得天赋点
unlockedTalents: string[]; // 已解锁天赋ID列表
// ========== 新增:传承道具 ==========
legacyItems: LegacyItemInventory[]; // 传承道具库存
legacySlots: number; // 当前传承槽位数
// ========== 新增:周目印记 ==========
playthroughStamps: PlaythroughStamp[]; // 周目历史记录
}
2.4 Buff标签系统
// Buff标签枚举
export type BuffTag =
// 来源标签
| '#Talent' // 来自天赋系统
| '#Legacy' // 来自传承道具
| '#Event' // 来自随机事件
| '#Equipment' // 来自装备
// 作用域标签
| '#Inn' // 客栈级Buff
| '#Staff' // 角色级Buff
| '#Global' // 全局级Buff
// 效果类型标签
| '#Business' // 经营类
| '#Jianghu' // 江湖类
| '#Mystic' // 奇门类
// 具体效果标签
| '#CostReduction' // 费用降低
| '#IncomeBoost' // 收入提升
| '#Security' // 治安相关
| '#Cleaning' // 清洁相关
| '#Cooking' // 烹饪相关
| '#Accounting' // 账房相关
| '#Reputation' // 声望相关
| '#EventMitigation' // 事件减益
| '#EventBoost' // 事件增益
;
3. 静态配置文件规范
3.1 天赋配置文件
文件位置:configs/talents.json
[
{
"id": "TALENT_BIZ_01",
"name": "佟家祖训",
"desc": "佟家世代经商的祖训,开局自带启动资金",
"branch": "BUSINESS",
"tier": 1,
"cost": 5,
"prerequisiteId": null,
"icon": "icons/talents/biz_01.png",
"buffConfig": {
"configId": "BUFF_TALENT_BIZ_01",
"targetType": "INN",
"targetId": null,
"tags": ["#Talent", "#Business", "#Startup"],
"duration": -1,
"modifiers": [
{
"targetAttribute": "startup_currency",
"calcType": "ADD",
"value": 100
}
]
},
"unlockCondition": null,
"sortOrder": 1
},
{
"id": "TALENT_BIZ_02",
"name": "精打细算",
"desc": "佟家世代经商的精明头脑,所有升级费用降低",
"branch": "BUSINESS",
"tier": 2,
"cost": 10,
"prerequisiteId": "TALENT_BIZ_01",
"icon": "icons/talents/biz_02.png",
"buffConfig": {
"configId": "BUFF_TALENT_BIZ_02",
"targetType": "INN",
"targetId": null,
"tags": ["#Talent", "#Business", "#CostReduction"],
"duration": -1,
"modifiers": [
{
"targetAttribute": "upgrade_cost_multiplier",
"calcType": "MULTIPLY",
"value": 0.97
}
]
},
"unlockCondition": null,
"sortOrder": 2
}
]
3.2 传承道具配置文件
文件位置:configs/legacy-items.json
[
{
"id": "LEGACY_CURRENCY_500",
"name": "佟家家底",
"desc": "佟湘玉从汉中带来的私房钱,虽然不多但足够应急",
"category": "LEGACY",
"subType": "CURRENCY_PACK",
"rarity": "RARE",
"icon": "icons/legacy/coin_pouch.png",
"flavorText": "这钱是额从汉中带来的...",
"isPermanent": false,
"maxHeld": 5,
"effects": [
{
"type": "STARTUP_CURRENCY",
"value": 500
}
],
"acquisitionSource": "LEGACY_SHOP",
"acquisitionId": "SHOP_CURRENCY_500",
"sortOrder": 1
},
{
"id": "LEGACY_TOKEN_BAI",
"name": "盗圣玉牌",
"desc": "白展堂的信物,持有者可在开局直接雇佣白展堂",
"category": "LEGACY",
"subType": "TOKEN",
"rarity": "EPIC",
"icon": "icons/legacy/bai_token.png",
"flavorText": "这块玉牌是老白行走江湖的凭证...",
"isPermanent": true,
"maxHeld": 1,
"effects": [
{
"type": "UNLOCK_NPC",
"unlockId": "bai"
}
],
"acquisitionSource": "ACHIEVEMENT",
"acquisitionId": "ACH_BAI_LOYALTY_MAX",
"sortOrder": 10
},
{
"id": "LEGACY_BUFF_FORTUNE",
"name": "财神符",
"desc": "七侠镇财神庙求来的符咒,开局自动获得财运Buff",
"category": "LEGACY",
"subType": "CONSUMABLE",
"rarity": "RARE",
"icon": "icons/legacy/fortune_charm.png",
"flavorText": "财神爷保佑,日进斗金...",
"isPermanent": false,
"maxHeld": 3,
"effects": [
{
"type": "STARTUP_BUFF",
"buffConfigId": "BUFF_LEGACY_FORTUNE"
}
],
"acquisitionSource": "LEGACY_SHOP",
"acquisitionId": "SHOP_FORTUNE_CHAR",
"sortOrder": 20
}
]
4. 核心业务逻辑
4.1 天赋点计算服务
/**
* 天赋点计算服务
* 用于周目结算时计算天赋点奖励
*/
export interface TalentPointReward {
base: number; // 基础点数
survivalBonus: number; // 存活天数奖励
reputationBonus: number; // 声望奖励
achievementBonus: number; // 成就奖励
outcomeBonus: number; // 结局奖励
total: number; // 总计
}
export class TalentPointCalculator {
/**
* 计算天赋点奖励
* @param stamp 周目印记
* @returns 天赋点奖励明细
*/
static calculate(stamp: PlaythroughStamp): TalentPointReward {
// 基础点数:每完成1个周目获得10点
const base = 10;
// 存活天数奖励:每存活1天+0.5点(上限30点)
const survivalBonus = Math.min(stamp.survivalDays * 0.5, 30);
// 声望奖励:最高声望/100(上限20点)
const reputationBonus = Math.min(Math.floor(stamp.maxReputation / 100), 20);
// 成就奖励:每个成就+2点
const achievementBonus = stamp.achievementsUnlocked.length * 2;
// 通关额外奖励
const outcomeBonus = stamp.outcome === 'SUCCESS' ? 20 : 0;
return {
base,
survivalBonus,
reputationBonus,
achievementBonus,
outcomeBonus,
total: base + survivalBonus + reputationBonus + achievementBonus + outcomeBonus
};
}
}
4.2 名望等级服务
/**
* 名望等级服务
* 用于计算名望等级和相关解锁
*/
export class ReputationService {
/**
* 根据名望值获取等级
* @param reputation 名望值
* @returns 名望等级
*/
static getLevel(reputation: number): ReputationLevel {
if (reputation >= 5000) return 'MYTHICAL';
if (reputation >= 1500) return 'LEGENDARY';
if (reputation >= 500) return 'RENOWNED';
if (reputation >= 100) return 'FAMOUS';
return 'UNKNOWN';
}
/**
* 获取名望等级配置
* @param level 名望等级
* @returns 等级配置
*/
static getConfig(level: ReputationLevel) {
return REPUTATION_LEVEL_CONFIG[level];
}
/**
* 计算单局声望折算名望(边际递减)
* @param runReputation 单局最高声望
* @returns 折算后的名望值
*/
static convertRunReputation(runReputation: number): number {
// 声望100以下不折算
if (runReputation <= 100) return 0;
// 100-500:1:1折算
if (runReputation <= 500) return runReputation - 100;
// 500-1000:0.5折算
if (runReputation <= 1000) return 400 + (runReputation - 500) * 0.5;
// 1000以上:0.25折算
return 650 + (runReputation - 1000) * 0.25;
}
}
4.3 天赋Buff激活服务
/**
* 天赋Buff激活服务
* 用于周目开始时激活天赋Buff
*/
export class TalentBuffActivator {
/**
* 激活所有已解锁天赋的Buff
* @param profile 全局账号数据
* @param talentConfigs 天赋配置列表
* @returns 生成的Buff实例列表
*/
static activateTalents(
profile: GlobalProfileExtended,
talentConfigs: StaticTalentConfig[]
): { innBuffs: RuntimeBuff[]; staffBuffs: Record<string, RuntimeBuff[]> } {
const innBuffs: RuntimeBuff[] = [];
const staffBuffs: Record<string, RuntimeBuff[]> = {};
// 筛选已解锁天赋
const activeTalents = talentConfigs.filter(config =>
profile.unlockedTalents.includes(config.id)
);
// 检查名望等级限制
const reputationConfig = ReputationService.getConfig(profile.reputationLevel);
const validTalents = activeTalents.filter(talent =>
talent.tier <= reputationConfig.maxTalentTier
);
// 生成Buff实例
validTalents.forEach(talent => {
const buff: RuntimeBuff = {
instanceId: generateUUID(),
configId: talent.buffConfig.configId,
tags: talent.buffConfig.tags,
durationRemaining: talent.buffConfig.duration,
sourceType: 'TALENT',
modifiers: talent.buffConfig.modifiers
};
if (talent.buffConfig.targetType === 'INN' || talent.buffConfig.targetType === 'GLOBAL') {
innBuffs.push(buff);
} else if (talent.buffConfig.targetType === 'STAFF' && talent.buffConfig.targetId) {
const staffId = talent.buffConfig.targetId;
if (!staffBuffs[staffId]) {
staffBuffs[staffId] = [];
}
staffBuffs[staffId].push(buff);
}
});
return { innBuffs, staffBuffs };
}
}
4.4 传承道具应用服务
/**
* 传承道具应用服务
* 用于周目开始时应用传承道具效果
*/
export class LegacyItemApplicator {
/**
* 应用传承道具效果
* @param selectedItems 选中的传承道具配置
* @param profile 全局账号数据
* @returns 初始游戏状态修改
*/
static applyItems(
selectedItems: LegacyItemConfig[],
profile: GlobalProfileExtended
): {
startupCurrency: number;
innBuffs: RuntimeBuff[];
unlockedNpcs: string[];
unlockedFacilities: string[];
unlockedRecipes: string[];
} {
let startupCurrency = 0;
const innBuffs: RuntimeBuff[] = [];
const unlockedNpcs: string[] = [];
const unlockedFacilities: string[] = [];
const unlockedRecipes: string[] = [];
selectedItems.forEach(item => {
item.effects.forEach(effect => {
switch (effect.type) {
case 'STARTUP_CURRENCY':
startupCurrency += effect.value || 0;
break;
case 'STARTUP_BUFF':
if (effect.buffConfigId) {
const buffConfig = loadBuffConfig(effect.buffConfigId);
if (buffConfig) {
innBuffs.push({
instanceId: generateUUID(),
configId: buffConfig.configId,
tags: [...buffConfig.tags, '#Legacy'],
durationRemaining: buffConfig.duration,
sourceType: 'LEGACY',
modifiers: buffConfig.modifiers
});
}
}
break;
case 'UNLOCK_NPC':
if (effect.unlockId) {
unlockedNpcs.push(effect.unlockId);
}
break;
case 'UNLOCK_FACILITY':
if (effect.unlockId) {
unlockedFacilities.push(effect.unlockId);
}
break;
case 'UNLOCK_RECIPE':
if (effect.unlockId) {
unlockedRecipes.push(effect.unlockId);
}
break;
}
});
});
// 消耗非永久道具
this.consumeItems(selectedItems, profile);
return {
startupCurrency,
innBuffs,
unlockedNpcs,
unlockedFacilities,
unlockedRecipes
};
}
/**
* 消耗非永久传承道具
*/
private static consumeItems(
selectedItems: LegacyItemConfig[],
profile: GlobalProfileExtended
): void {
selectedItems
.filter(item => !item.isPermanent)
.forEach(item => {
const inventory = profile.legacyItems.find(i => i.itemId === item.id);
if (inventory) {
inventory.quantity--;
if (inventory.quantity <= 0) {
profile.legacyItems = profile.legacyItems.filter(i => i.itemId !== item.id);
}
}
});
}
}
5. 存档兼容性设计
5.1 存档版本号
// 存档版本常量
export const SAVE_SCHEMA_VERSION = 3; // 当前版本
// 版本迁移映射
export const SAVE_MIGRATIONS: Record<number, (data: any) => any> = {
1: (data) => migrateV1ToV2(data),
2: (data) => migrateV2ToV3(data),
};
5.2 V2到V3迁移(新增天赋与传承字段)
function migrateV2ToV3(data: any): GlobalProfileExtended {
return {
...data,
// 新增字段默认值
accountReputation: data.accountReputation || 0,
reputationLevel: data.reputationLevel || 'UNKNOWN',
talentPoints: data.talentPoints || 0,
totalTalentPointsEarned: data.totalTalentPointsEarned || 0,
unlockedTalents: data.unlockedTalents || [],
legacyItems: data.legacyItems || [],
legacySlots: data.legacySlots || 1,
playthroughStamps: data.playthroughStamps || [],
};
}
6. 事件总线集成
6.1 天赋相关事件
// 天赋系统事件类型
export const TALENT_EVENTS = {
// 天赋解锁
TALENT_UNLOCKED: 'TALENT_UNLOCKED',
// 天赋点变化
TALENT_POINTS_CHANGED: 'TALENT_POINTS_CHANGED',
// 名望变化
REPUTATION_CHANGED: 'REPUTATION_CHANGED',
// 名望等级提升
REPUTATION_LEVEL_UP: 'REPUTATION_LEVEL_UP',
// 传承道具获取
LEGACY_ITEM_ACQUIRED: 'LEGACY_ITEM_ACQUIRED',
// 传承道具使用
LEGACY_ITEM_USED: 'LEGACY_ITEM_USED',
// 周目结算完成
PLAYTHROUGH_SETTLED: 'PLAYTHROUGH_SETTLED',
} as const;
6.2 事件数据接口
// 天赋解锁事件数据
export interface TalentUnlockedEventData {
talentId: string;
talentName: string;
branch: TalentBranch;
cost: number;
}
// 名望变化事件数据
export interface ReputationChangedEventData {
oldValue: number;
newValue: number;
delta: number;
source: string;
}
// 周目结算事件数据
export interface PlaythroughSettledEventData {
stamp: PlaythroughStamp;
talentPointReward: TalentPointReward;
reputationGained: number;
}
7. UI组件接口
7.1 天赋树组件Props
export interface TalentTreePanelProps {
profile: GlobalProfileExtended;
talentConfigs: StaticTalentConfig[];
onUnlockTalent: (talentId: string) => void;
}
7.2 传承道具选择组件Props
export interface LegacyItemSelectionProps {
profile: GlobalProfileExtended;
legacyItemConfigs: LegacyItemConfig[];
maxSlots: number;
onConfirm: (selectedItemIds: string[]) => void;
onCancel: () => void;
}
7.3 周目结算组件Props
export interface PlaythroughSettlementProps {
stamp: PlaythroughStamp;
talentPointReward: TalentPointReward;
reputationGained: number;
newReputationLevel: ReputationLevel;
onConfirm: () => void;
}
8. 存储Key规范
// 存储Key常量
export const STORAGE_KEYS = {
// 全局账号数据(扩展版)
GLOBAL_PROFILE: 'tongfu_global_profile_v3',
// 天赋配置缓存
TALENT_CONFIGS_CACHE: 'tongfu_talent_configs_cache',
// 传承道具配置缓存
LEGACY_ITEMS_CACHE: 'tongfu_legacy_items_cache',
} as const;
9. 测试用例
9.1 天赋点计算测试
describe('TalentPointCalculator', () => {
it('应正确计算基础天赋点', () => {
const stamp: PlaythroughStamp = {
playthroughId: 1,
outcome: 'BANKRUPTCY',
survivalDays: 10,
maxReputation: 200,
totalSilverEarned: 5000,
achievementsUnlocked: ['ACH_001', 'ACH_002'],
talentPointsEarned: 0,
specialFlags: [],
timestamp: Date.now()
};
const result = TalentPointCalculator.calculate(stamp);
expect(result.base).toBe(10);
expect(result.survivalBonus).toBe(5); // 10 * 0.5
expect(result.reputationBonus).toBe(2); // 200 / 100
expect(result.achievementBonus).toBe(4); // 2 * 2
expect(result.outcomeBonus).toBe(0); // 非通关
expect(result.total).toBe(21);
});
it('应正确计算通关天赋点', () => {
const stamp: PlaythroughStamp = {
playthroughId: 2,
outcome: 'SUCCESS',
survivalDays: 30,
maxReputation: 1000,
totalSilverEarned: 50000,
achievementsUnlocked: ['ACH_001', 'ACH_002', 'ACH_003'],
talentPointsEarned: 0,
specialFlags: [],
timestamp: Date.now()
};
const result = TalentPointCalculator.calculate(stamp);
expect(result.base).toBe(10);
expect(result.survivalBonus).toBe(15); // 30 * 0.5
expect(result.reputationBonus).toBe(10); // 1000 / 100
expect(result.achievementBonus).toBe(6); // 3 * 2
expect(result.outcomeBonus).toBe(20); // 通关
expect(result.total).toBe(61);
});
});
9.2 名望等级测试
describe('ReputationService', () => {
it('应正确计算名望等级', () => {
expect(ReputationService.getLevel(0)).toBe('UNKNOWN');
expect(ReputationService.getLevel(99)).toBe('UNKNOWN');
expect(ReputationService.getLevel(100)).toBe('FAMOUS');
expect(ReputationService.getLevel(500)).toBe('RENOWNED');
expect(ReputationService.getLevel(1500)).toBe('LEGENDARY');
expect(ReputationService.getLevel(5000)).toBe('MYTHICAL');
});
it('应正确折算声望', () => {
expect(ReputationService.convertRunReputation(50)).toBe(0);
expect(ReputationService.convertRunReputation(150)).toBe(50);
expect(ReputationService.convertRunReputation(500)).toBe(400);
expect(ReputationService.convertRunReputation(750)).toBe(525);
expect(ReputationService.convertRunReputation(1000)).toBe(650);
expect(ReputationService.convertRunReputation(1500)).toBe(775);
});
});
10. 性能优化建议
10.1 配置缓存
- 天赋配置和传承道具配置在游戏初始化时一次性加载并缓存
- 使用
useMemo缓存计算结果
10.2 懒加载
- 天赋树UI组件采用懒加载
- 传承道具详情弹窗按需加载
10.3 批量更新
- 周目结算时批量更新GlobalProfile
- 使用事务性更新避免中间状态
11. 后续扩展预留
11.1 天赋重置功能
// 预留接口
export interface TalentResetService {
resetTalent(talentId: string, profile: GlobalProfileExtended): number; // 返回返还的天赋点
resetAllTalents(profile: GlobalProfileExtended): number;
getResetCost(profile: GlobalProfileExtended): number; // 重置费用(阅历)
}
11.2 传承道具合成
// 预留接口
export interface LegacyItemSynthesisService {
canSynthesize(itemIds: string[]): boolean;
synthesize(itemIds: string[]): LegacyItemConfig;
getSynthesisResult(itemIds: string[]): LegacyItemConfig;
}