diff --git a/apps/web/src/containers/Summary.tsx b/apps/web/src/containers/Summary.tsx
index 9255579..f9c5bb3 100644
--- a/apps/web/src/containers/Summary.tsx
+++ b/apps/web/src/containers/Summary.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useState, useRef } from 'react'
+import { useEffect, useState, useRef, useMemo } from 'react'
import { usePicked, useEnd, useProfile } from '@remake/hooks'
import { useEndJudge } from '@/hooks/judge'
import { properties, judgeDisplay } from '@/display'
@@ -27,26 +27,24 @@ interface TalentListProps {
}
function TalentList({ picked, picker }: TalentListProps) {
const [profile] = useProfile()
- const [talents, setTalents] = useState(usePicked())
+ const items = usePicked()
+ const talents = useMemo(() => {
+ if (!isDev || !profile.locked) return items
+ return new Set([...items, ...profile.locked])
+ }, [])
const hasInitialized = useRef(false)
-
useEffect(() => {
if (!profile.locked) return
- let currentTalents = talents
- if (isDev) {
- currentTalents = new Set([...talents, ...profile.locked])
- setTalents(currentTalents)
- }
-
if (!hasInitialized.current) {
for (const id of profile.locked) {
- if (currentTalents.has(id) && !picked.has(id)) {
+ if (talents.has(id) && !picked.has(id)) {
picker(id)
}
}
hasInitialized.current = true
}
- }, [profile, talents, picked, picker])
+ }, [picked, picker])
+
return (
{Array.from(talents, id => (
diff --git a/docs/remake.md b/docs/remake.md
deleted file mode 100644
index 4d9b2a5..0000000
--- a/docs/remake.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## 流程
-
-重开
- 初始化
- 抽天赋(包含继承的天赋)
- 天赋选择(检测天赋冲突)
- 天赋替换(检测天赋冲突)
- 点数分配(天赋额外点数)
- 游戏循环
- 年龄增加一岁
- 天赋触发
- 事件触发(从对应年龄事件池随机事件)
- 判断是否结束(生命值小于 1 结束)
- 总评
- 天赋继承
- 存档数据
- 重回首页
\ No newline at end of file
diff --git a/packages/condition/index.ts b/packages/condition/index.ts
index 629d0f2..032e033 100644
--- a/packages/condition/index.ts
+++ b/packages/condition/index.ts
@@ -188,16 +188,3 @@ function checkProp(property: PropertyContainer, condition: string): boolean {
return false
}
}
-
-export function extractMaxTriggers(condition: string): number {
- // Assuming only age related talents can be triggered multiple times.
- const RE_AGE_CONDITION = /AGE\?\[([0-9,]+)\]/
- const matchObject = RE_AGE_CONDITION.exec(condition)
-
- if (matchObject === null) {
- // Not age related, single trigger.
- return 1
- }
-
- return matchObject[1]?.split(',')?.length ?? 1
-}
diff --git a/packages/core/src/achievement.spec.ts b/packages/core/src/achievement.spec.ts
index 3177c78..69aae26 100644
--- a/packages/core/src/achievement.spec.ts
+++ b/packages/core/src/achievement.spec.ts
@@ -17,6 +17,7 @@ describe('Achievement', () => {
intelligence: 5,
strength: 5,
money: 5,
+ spirit: 5,
}
test('trigger [times:500]', () => {
diff --git a/packages/core/src/event.spec.ts b/packages/core/src/event.spec.ts
index 7ccf126..198ed6b 100644
--- a/packages/core/src/event.spec.ts
+++ b/packages/core/src/event.spec.ts
@@ -16,6 +16,7 @@ describe('Event', () => {
intelligence: 10,
strength: 0,
money: 0,
+ spirit: 5,
}
test('branch 10003:0 [玉佩]', () => {
diff --git a/packages/core/src/game.spec.ts b/packages/core/src/game.spec.ts
index e23b4ba..cddf7f7 100644
--- a/packages/core/src/game.spec.ts
+++ b/packages/core/src/game.spec.ts
@@ -17,6 +17,7 @@ describe('Achievement', () => {
intelligence: 5,
strength: 5,
money: 5,
+ spirit: 5,
}
test('talentsPicked', () => {
diff --git a/packages/core/src/state.spec.ts b/packages/core/src/state.spec.ts
index 57c3152..5d067da 100644
--- a/packages/core/src/state.spec.ts
+++ b/packages/core/src/state.spec.ts
@@ -2,7 +2,7 @@ import { expect, test, describe } from 'bun:test'
import { parse, type ConditionNode } from '@remake/condition'
import { achievements, events, talents } from '@remake/data'
-import type { GameState, ProfileState, Properties } from './state'
+import type { FlatState, GameState, ProfileState, Properties } from './state'
import { createFlatState, createHLProperties, propsEffect } from './state'
import { SupportedFlatStateKeys } from './state'
import { enableMapSet } from 'immer'
@@ -11,7 +11,10 @@ enableMapSet()
/**
* 核心递归辅助函数:从多维语法树节点中提取所有属性名
*/
-function extractKeysFromNode(node: ConditionNode, properties: Set) {
+function extractKeysFromNode(
+ node: ConditionNode,
+ properties: Set,
+) {
if (Array.isArray(node)) {
for (const subNode of node) {
extractKeysFromNode(subNode, properties)
@@ -22,7 +25,7 @@ function extractKeysFromNode(node: ConditionNode, properties: Set) {
// 匹配操作符(>) {
/**
* 从条件字符串中提取所有使用到的属性键名
*/
-function getPropertiesFromCondition(condition: string): Set {
+function getPropertiesFromCondition(condition: string): Set {
const parsedConditions = parse(condition)
- const properties = new Set()
+ const properties = new Set()
extractKeysFromNode(parsedConditions, properties)
return properties
}
@@ -205,7 +208,13 @@ describe('State', () => {
)
})
- const allocation = { charm: 5, intelligence: 5, strength: 5, money: 5 }
+ const allocation = {
+ charm: 5,
+ intelligence: 5,
+ strength: 5,
+ money: 5,
+ spirit: 5,
+ }
test('createHLProperties', () => {
const props = createHLProperties(allocation)
expect(props.current.charm).toBe(allocation.charm)
@@ -213,7 +222,7 @@ describe('State', () => {
expect(props.current.strength).toBe(allocation.strength)
expect(props.current.money).toBe(allocation.money)
expect(props.current.age).toBe(-1)
- expect(props.current.spirit).toBe(0)
+ expect(props.current.spirit).toBe(5)
})
test('propsEffect', () => {
diff --git a/packages/core/src/talent.spec.ts b/packages/core/src/talent.spec.ts
index 11a8086..9d5a2a6 100644
--- a/packages/core/src/talent.spec.ts
+++ b/packages/core/src/talent.spec.ts
@@ -30,11 +30,11 @@ describe('Talent', () => {
test('pull external', () => {
const p = produce(profile, draft => {
- draft.lockedTalent = 1001
+ draft.locked = [1001]
})
const result = pull(options, p)
expect(result.length).toBe(options.count)
- expect(result).toContain(p.lockedTalent!)
+ expect(result).toContain(p.locked![0]!)
})
test('pull rate', () => {
diff --git a/packages/data/BUGS.md b/packages/data/BUGS.md
new file mode 100644
index 0000000..132dbab
--- /dev/null
+++ b/packages/data/BUGS.md
@@ -0,0 +1,9 @@
+## Bugs
+
+### 复活Bug
+ age 400
+ -> 寿元终
+ -> 天赋复活
+ age 401
+ -> 无可随机事件
+ -> 报错
\ No newline at end of file
diff --git a/packages/data/src/event.types.ts b/packages/data/src/event.types.ts
index 82380ce..08f5a0b 100644
--- a/packages/data/src/event.types.ts
+++ b/packages/data/src/event.types.ts
@@ -47,6 +47,8 @@ export type Event = {
readonly exclude?: string
/** 分支路线 */
readonly branch?: EventBranch[]
+ /** 是否需要格式化 */
+ readonly format?: boolean
}
// @vt-types-end
diff --git a/packages/data/src/event.xlsx b/packages/data/src/event.xlsx
index 7dcce29..b418804 100644
Binary files a/packages/data/src/event.xlsx and b/packages/data/src/event.xlsx differ
diff --git a/packages/vitex/index.ts b/packages/vitex/index.ts
index b846f14..4e5bade 100644
--- a/packages/vitex/index.ts
+++ b/packages/vitex/index.ts
@@ -43,3 +43,18 @@ export function keys(
const filterSet = new Set(filter)
return allKeys.filter(key => !filterSet.has(key)) as Exclude[]
}
+// 定义获取字段值的方法签名
+export type GetValueFn = (
+ fieldName: string,
+) => string | number | boolean | null | undefined
+export function format(str: string, getValueFn: GetValueFn): string {
+ if (!str) return ''
+ return str.replace(
+ /\{([^}]+)\}/g,
+ (match: string, fieldName: string): string => {
+ const value = getValueFn(fieldName)
+ if (value === undefined || value === null) return match
+ return String(value)
+ },
+ )
+}