import { useGameStore } from '../store' import { Character, GameState } from '../../game/types/domain' import { describeRealm, nextRealm } from '../../game/data/realms' import { describeRoots, ROOT_GRADE_NAMES } from '../../game/data/elements' import { TRAITS } from '../../game/data/traits' import { TECHNIQUES } from '../../game/data/techniques' import { ITEMS, ARTIFACT_POWER } from '../../game/data/items' import { combatPowerOf } from '../../game/engine/systems/combat' import { lifespanOf } from '../../game/engine/systems/lifecycle' import { POSTS, POST_ORDER } from '../../game/data/posts' import { buildBiography } from '../../game/core/biography' function aspName(c: Character): string { const map: Record = { dao: '志向·求道', zhen: '志向·镇族', cheng: '志向·承宗', shang: '志向·商略', bing: '志向·兵略', geng: '志向·耕读', yun: '志向·云游' } return map[c.aspiration ?? ''] ?? '志向·未定' } function fitTag(c: Character): string | null { const t = TECHNIQUES.find((x) => x.id === c.techniqueId) if (!t) return null return t.element === c.roots.primary ? `本命·${t.element}契合` : null } function deadish(c: Character): boolean { return !c.alive } function gradeShort(g: number): string { const map: Record = { 0: '凡', 1: '黄', 2: '玄', 3: '地', 4: '天', 5: '仙' } return map[g] ?? '?' } function pillCount(s: GameState, id: string): number { return s.family.inventory[id] ?? 0 } function equipableItems(member: Character, s: GameState): string[] { const inv = Object.keys(ARTIFACT_POWER).filter((ai) => (s.family.inventory[ai] ?? 0) > 0) if (member.equipment && !inv.includes(member.equipment)) inv.push(member.equipment) return inv } export function MemberModal({ member }: { member: Character }) { const world = useGameStore((s) => s.world) const setSelected = useGameStore((s) => s.setSelected) const bump = useGameStore((s) => s.bump) if (!world) return null const w = world const s = w.state const next = nextRealm(member.realm) const nextName = next ? describeRealm(next) : '已至巅峰' const tech = TECHNIQUES.find((t) => t.id === member.techniqueId) const power = member.alive ? combatPowerOf(w, member) : 0 const lifespan = lifespanOf(w, member) return (
setSelected(undefined)}>
e.stopPropagation()}>
{member.name} {!member.alive && · 殁}
第{member.generation}代 · {member.gender === 'male' ? '男' : '女'} · {w.ageOf(member)}岁 · 寿数约{lifespan} · {describeRoots(member.roots)}
境界进度{describeRealm(member.realm)} {Math.floor(member.realmProgress)}%
下一关= 100 ? 'gold' : ''}>{nextName}
战力{Math.round(power)}
状态 {member.state === 'meditation' ? '闭关' : member.state === 'expedition' ? '外出' : member.state === 'wounded' ? '养伤' : member.state === 'apprentice' ? '寄读' : '无事'}
气血{Math.round(member.health)}
功法{tech ? `${tech.name}(${gradeShort(tech.grade)}阶)` : member.realm.major === 'mortal' ? '—' : '未习功法'}
法宝{member.equipment ? `${ITEMS[member.equipment].name}(+${Math.round((ARTIFACT_POWER[member.equipment] ?? 0) * 100)}%)` : '—'}
姻亲{member.spouseId ? s.members[member.spouseId]?.name ?? '' : member.spouseHouse ?? '未婚'}
悟性{member.perception}/10
根骨{member.physique}/10
心性{member.mind}/10
魅力{member.charm}/10
气运{member.fortune}/12
品性{member.fortune ? (member.fortune > 7 ? '俊逸' : '端正') : '—'}
秉性
{member.traits.map((t) => ( {TRAITS[t]?.name ?? t} ))} {member.traits.length === 0 && 平淡无奇}
起居
{member.alive && member.state !== 'expedition' && ( )} {member.alive && member.realmProgress >= 100 && member.realm.major !== 'spirit' && ( )} {member.alive && ( <> {member.realm.major !== 'mortal' && ( )} {member.realmProgress >= 70 && member.realm.major !== 'mortal' && ( )} )}
{member.alive && (
传功(藏书阁所录)
{s.family.techniques.map((tid) => ( ))} {s.family.techniques.length === 0 && 无典籍存库}
)} {member.alive && (
法宝装备(府库所列)
{equipableItems(member, s).length === 0 && 府库暂无存货(可往坊市购得或于秘境寻获)} {equipableItems(member, s).map((ai) => ( ))}
)} {member.alive && (
职事(族中分工)
{POST_ORDER.filter((pid) => pid !== 'head').map((pid) => { const def = POSTS[pid] const maxed = w.postCount(pid) >= def.max && member.post !== pid return ( ) })}
)} {member.alive && (
志向与契合
{aspName(member)} {fitTag(member) && {fitTag(member)}}
)}
小传(春秋原记录)
{buildBiography(w.state, member.id).map((l, i) => (
{l.label && {l.label} · } {l.text}
))}
{member.alive && w.canMarry(member.id) && (
指婚(寻配族内共居者,远亲无碍)
{w.marriageCandidatesOf(member.id).map((cand) => ( ))} {w.marriageCandidatesOf(member.id).length === 0 && 暂无适配人选}
)}
{member.children.length > 0 && ( 子女:{member.children.map((cid) => s.members[cid]?.name ?? '?').join('、')} )}
) }