v0.1.0: 仙途家族志 · Chronicle of the Immortal Clan
家族模拟器首版:修仙/经营/战斗/外交/叙事全套系统 - Electron + React + TS + MetonaSqlark(aria+OPFS) - 水墨中国风 UI - 引擎种子随机、确定性可回放 - 19 项单元测试、端到端冒烟验证
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { useGameStore } from '../store'
|
||||
import { BUILDINGS } from '../../game/data/buildings'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
export default function TerritoryPanel() {
|
||||
const world = useGameStore((s) => s.world)
|
||||
const bump = useGameStore((s) => s.bump)
|
||||
const revision = useGameStore((s) => s.revision)
|
||||
void revision
|
||||
if (!world) return null
|
||||
const fam = world.state.family
|
||||
const ids = useMemo(() => Object.keys(BUILDINGS), [])
|
||||
|
||||
const levelLabel = (l: number) => '·'.repeat(l) + '。'.repeat(5 - l)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="help-text">
|
||||
族产经营:建造建筑后每月自动产出;坊市、丹房等基础设施可解锁功能。
|
||||
灵石与灵矿不足则无法建造或升级。
|
||||
</div>
|
||||
<div className="bld-grid">
|
||||
{ids.map((id) => {
|
||||
const def = BUILDINGS[id]
|
||||
if (!def) return null
|
||||
const level = fam.buildings[id] ?? 0
|
||||
const built = level > 0
|
||||
const cost = built && level >= def.maxLevel ? null : def.upgradeCost(built ? level + 1 : 1)
|
||||
const produce = def.produceTable ? def.produceTable(built ? level : 1) : null
|
||||
const canUpgrade =
|
||||
!!cost &&
|
||||
fam.stones >= cost.stones &&
|
||||
fam.inventory['lingkuang'] >= cost.lingkuang
|
||||
return (
|
||||
<div key={id} className={`bld-card ${built ? '' : 'dim2'}`}>
|
||||
<div className="bld-head">
|
||||
<span className="bld-icon">{def.icon}</span>
|
||||
<div>
|
||||
<div>{def.name}</div>
|
||||
<div className="dim2" style={{ fontSize: '0.75rem' }}>{def.kind === 'produce' ? '产出' : '功效'}</div>
|
||||
</div>
|
||||
<span className="bld-lv">{built ? `${level}级` : ''}</span>
|
||||
</div>
|
||||
<div className="bld-desc">{def.desc}</div>
|
||||
{produce && Object.keys(produce).length > 0 && (
|
||||
<div className="bld-prod">
|
||||
{Object.entries(produce)
|
||||
.filter(([k]) => k !== 'beastcore' || (built && level >= 3))
|
||||
.map(([k, v]) => `${itemLabel(k)} ×${v}`)
|
||||
.join(' / ')}
|
||||
/月
|
||||
</div>
|
||||
)}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 'auto' }}>
|
||||
{built ? (
|
||||
<>
|
||||
{level < def.maxLevel ? (
|
||||
<button
|
||||
className="btn btn-sm"
|
||||
disabled={!canUpgrade}
|
||||
onClick={() => {
|
||||
world.upgrade(id)
|
||||
bump()
|
||||
}}
|
||||
>
|
||||
升至{level + 1}级({cost?.stones ?? 0}灵石 + {cost?.lingkuang ?? 0}灵矿)
|
||||
</button>
|
||||
) : (
|
||||
<span className="gold">已臻极致</span>
|
||||
)}
|
||||
<span className="dim2" style={{ marginLeft: 'auto' }}>{levelLabel(level)}</span>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
disabled={!canUpgrade}
|
||||
onClick={() => {
|
||||
world.build(id)
|
||||
bump()
|
||||
}}
|
||||
>
|
||||
营建({cost?.stones ?? 0}灵石 + {cost?.lingkuang ?? 0}灵矿)
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function itemLabel(k: string): string {
|
||||
const map: Record<string, string> = {
|
||||
stone: '灵石',
|
||||
lingcao: '灵草',
|
||||
lingkuang: '灵矿',
|
||||
beastcore: '兽核'
|
||||
}
|
||||
return map[k] ?? k
|
||||
}
|
||||
Reference in New Issue
Block a user