v0.1.0: 仙途家族志 · Chronicle of the Immortal Clan

家族模拟器首版:修仙/经营/战斗/外交/叙事全套系统
- Electron + React + TS + MetonaSqlark(aria+OPFS)
- 水墨中国风 UI
- 引擎种子随机、确定性可回放
- 19 项单元测试、端到端冒烟验证
This commit is contained in:
2026-08-23 00:04:16 +08:00
commit adb22f0558
69 changed files with 14305 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
import { useGameStore } from '../store'
import { applyEventChoice } from '../../game/engine/systems/events'
import { eventCategoryName, EventDef } from '../../game/data/events'
export function EventModal() {
const pendingEventId = useGameStore((s) => s.pendingEventId)
const pendingEventDef = useGameStore((s) => s.pendingEventDef)
const world = useGameStore((s) => s.world)
const bump = useGameStore((s) => s.bump)
const setSpeed = useGameStore((s) => s.setSpeed)
if (!pendingEventId || !pendingEventDef || !world) return null
const choose = (idx: number) => {
applyEventChoice(world, pendingEventId, idx)
useGameStore.setState({ pendingEventId: undefined, pendingEventDef: undefined })
bump()
// 重要事务后暂停推算,给玩家喘息
const sp = useGameStore.getState().speed
if (sp > 1) setSpeed(1)
}
return (
<div className="modal-outer">
<div className="modal">
<div className="modal-title">{pendingEventDef.name}</div>
<div className="modal-cat">
{eventCategoryName(pendingEventDef.category)}
{pendingEventDef.once && ' · 仅此一次'}
</div>
<div className="modal-text">{pendingEventDef.text}</div>
<div className="modal-opts">
{pendingEventDef.options.map((o, i) => (
<button key={i} className="opt-btn" onClick={() => choose(i)}>
{o.label}
{o.hint && <span className="hint">{o.hint}</span>}
</button>
))}
</div>
</div>
</div>
)
}