summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop
diff options
context:
space:
mode:
Diffstat (limited to 'src/LivingVillage.Desktop')
-rw-r--r--src/LivingVillage.Desktop/Assets/cjk-glyph-atlas.pngbin89701 -> 90591 bytes
-rw-r--r--src/LivingVillage.Desktop/Assets/cjk-glyphs.txt3
-rw-r--r--src/LivingVillage.Desktop/ChineseText.fs2
-rw-r--r--src/LivingVillage.Desktop/CjkGlyphAtlas.fs2
-rw-r--r--src/LivingVillage.Desktop/Game.fs94
-rw-r--r--src/LivingVillage.Desktop/Interaction.fs2
-rw-r--r--src/LivingVillage.Desktop/TaskRuntime.fs14
7 files changed, 115 insertions, 2 deletions
diff --git a/src/LivingVillage.Desktop/Assets/cjk-glyph-atlas.png b/src/LivingVillage.Desktop/Assets/cjk-glyph-atlas.png
index 69662c0..6d422e7 100644
--- a/src/LivingVillage.Desktop/Assets/cjk-glyph-atlas.png
+++ b/src/LivingVillage.Desktop/Assets/cjk-glyph-atlas.png
Binary files differ
diff --git a/src/LivingVillage.Desktop/Assets/cjk-glyphs.txt b/src/LivingVillage.Desktop/Assets/cjk-glyphs.txt
index 5c37717..7532222 100644
--- a/src/LivingVillage.Desktop/Assets/cjk-glyphs.txt
+++ b/src/LivingVillage.Desktop/Assets/cjk-glyphs.txt
@@ -1,4 +1,5 @@
×
+→
一
上
不
@@ -83,7 +84,9 @@
圃
土
在
+地
坏
+块
墙
备
夏
diff --git a/src/LivingVillage.Desktop/ChineseText.fs b/src/LivingVillage.Desktop/ChineseText.fs
index 9789ae7..349bbec 100644
--- a/src/LivingVillage.Desktop/ChineseText.fs
+++ b/src/LivingVillage.Desktop/ChineseText.fs
@@ -218,6 +218,8 @@ module ChineseText =
"转卖"
"观察记事"
"论理"
+ "自家地块"
+ "→"
"剧情线"
"雨水与年成"
"水位与收成"
diff --git a/src/LivingVillage.Desktop/CjkGlyphAtlas.fs b/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
index ab03039..a295f10 100644
--- a/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
+++ b/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
@@ -11,7 +11,7 @@ module CjkGlyphAtlas =
// Keep this table sorted and stable so the generated PNG has a reproducible layout.
let private characterTable =
- "×一上不与业东两中为主乐乡书买了争事于互些交人今从以件价任众会传位体作使保信倍停先入关内册再农冬准几出分切到前剧力功务动助匀包北单卖南卷原去友取受口只可各同和品回围圃土在坏墙备夏多夜大天夫失头好始子存完定家察对将小尚就层居屋工差己已巴巷币布帮常平年庄库应庙度开式当录待得心必态怒总恼情愁意戏成或户打找报拒择指挑捕据接提播操收改效敌数文料新方无日旧时明昏易春是晓晚晨景暂更最有未村束板林果柴标格档桥歉段民水求江没法涨淡清渔游热照物状玩理瓦生用田留白的盐目看真石确社离秋移稳空竹笑第米粮精系紧纭纷线结给绝继绪续置翻耕聊职背能自范茶获菜落衅行西观认讨议记讲论设访试话询说请读谅谈败货贩资走足路跳车转轴过近返还进迫退送选速道邻郎都里量金鉴钱门闭问闯闲间闻附雨零需面页项须食饥饿香鱼黄黛,:"
+ "×→一上不与业东两中为主乐乡书买了争事于互些交人今从以件价任众会传位体作使保信倍停先入关内册再农冬准几出分切到前剧力功务动助匀包北单卖南卷原去友取受口只可各同和品回围圃土在地坏块墙备夏多夜大天夫失头好始子存完定家察对将小尚就层居屋工差己已巴巷币布帮常平年庄库应庙度开式当录待得心必态怒总恼情愁意戏成或户打找报拒择指挑捕据接提播操收改效敌数文料新方无日旧时明昏易春是晓晚晨景暂更最有未村束板林果柴标格档桥歉段民水求江没法涨淡清渔游热照物状玩理瓦生用田留白的盐目看真石确社离秋移稳空竹笑第米粮精系紧纭纷线结给绝继绪续置翻耕聊职背能自范茶获菜落衅行西观认讨议记讲论设访试话询说请读谅谈败货贩资走足路跳车转轴过近返还进迫退送选速道邻郎都里量金鉴钱门闭问闯闲间闻附雨零需面页项须食饥饿香鱼黄黛,:"
let characters = characterTable.ToCharArray()
let rowCount = (characters.Length + columns - 1) / columns
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs
index a0e6fc0..ba925f3 100644
--- a/src/LivingVillage.Desktop/Game.fs
+++ b/src/LivingVillage.Desktop/Game.fs
@@ -343,6 +343,12 @@ type LivingVillageGame() as this =
let mutable p65Step = 0
let mutable p65PendingName = ""
let mutable p65Pending = false
+ // P67 证据钩子(职业每日任务 UI 目标展示):农夫真实开局 → 找到当日「帮工」任务 →
+ // 拍带目标帧(帮工:… → 村民 N)与同模板无目标帧(帮工:…,文案与旧版逐字节一致)各一帧。
+ let p67ShotMode = Environment.GetEnvironmentVariable("LV_P67_SHOT") = "1"
+ let mutable p67Step = 0
+ let mutable p67PendingName = ""
+ let mutable p67Pending = false
// P45 证据钩子:LV_P45_SHOT=1 时拍角色 idle / 行走朝下 / 行走朝右 三帧(真实游戏截图)。
let p45ShotMode = Environment.GetEnvironmentVariable("LV_P45_SHOT") = "1"
let mutable p45Step = 0
@@ -1238,6 +1244,84 @@ type LivingVillageGame() as this =
m5View.Status
p65Step <- p65Step + 1
+ /// P67 证据:任务面板的目标展示(带目标 / 无目标各一帧),走真实每日任务纯函数生成的 DailyTask。
+ member private this.PrepareP67Shot () =
+ let noonOfDay (day: int64) : int64 =
+ day * Sim.ticksPerDay + M6Presentation.resolveStartTick (Some 12.0) false
+ let targets = WorldBootstrap.reachableTargets world
+ let dayTask (day: int64) (targeted: bool) =
+ if targeted then
+ Occupation.dailyTaskOfWith targets 42UL (Occupation.occupationSeedOf Occupation.Farmer) day Occupation.Farmer
+ else
+ Occupation.dailyTaskOf 42UL (Occupation.occupationSeedOf Occupation.Farmer) day Occupation.Farmer
+ // 找一天当日任务为「帮工」(有目标语义),使两帧同模板可直接对照。
+ let mutable helpDay = 0L
+ let mutable found = false
+ for day in 0L .. 120L do
+ if not found then
+ match dayTask day true with
+ | Some task when task.TemplateId = Occupation.HelpWork -> helpDay <- day; found <- true
+ | _ -> ()
+ let setToday (task: Occupation.DailyTask) =
+ match m5View.Task with
+ | Some state -> m5View <- { m5View with Task = Some { state with Today = Some task } }
+ | None -> ()
+ let ask (command: M5Command) =
+ let nextWorld, nextView = M5Interaction.apply command world m5View
+ world <- nextWorld
+ m5View <- nextView
+ if not p67Pending then
+ match p67Step with
+ | 0 ->
+ let tick = noonOfDay helpDay
+ world <- { world with Tick = tick; Time = float tick * Sim.dtSeconds }
+ match dayTask helpDay true with
+ | Some task -> setToday task
+ | None -> ()
+ ask M5Command.ShowTaskPanel
+ this.CenterCamera()
+ p67PendingName <- "p67-target"
+ p67Pending <- true
+ | 1 ->
+ match dayTask helpDay false with
+ | Some task -> setToday task
+ | None -> ()
+ p67PendingName <- "p67-wildcard"
+ p67Pending <- true
+ | _ ->
+ printfn "p67-shot=done"
+ this.Exit()
+
+ /// P67 证据:落盘并打印帧名/面板/模板/目标/整行文案/缺字槽位,供 analyze 核验。
+ member private this.CaptureP67Shot () =
+ if p67Pending then
+ p67Pending <- false
+ System.IO.Directory.CreateDirectory recordDirectory |> ignore
+ this.SaveBackBuffer(sprintf "%s/%s.png" recordDirectory p67PendingName)
+ let lines = M5Interaction.panelLines world m5View
+ let missingSlots =
+ lines
+ |> List.sumBy (fun line ->
+ line
+ |> Seq.filter (fun c -> c <> ' ' && not (PixelText.isRenderable (string c)))
+ |> Seq.length)
+ let templateText, targetText, lineText =
+ match m5View.Task |> Option.bind (fun state -> state.Today) with
+ | None -> "none", "<none>", "<none>"
+ | Some task ->
+ Occupation.taskNameOf task.TemplateId,
+ (TaskRuntime.targetText task |> Option.defaultValue "<none>"),
+ (TaskRuntime.taskLine task "进行中")
+ printfn
+ "p67-shot=%s panel=%s template=%s target=%s line=%s missing_glyph_slots=%d"
+ p67PendingName
+ (M5Interaction.panelName m5View)
+ templateText
+ targetText
+ lineText
+ missingSlots
+ p67Step <- p67Step + 1
+
member private this.PrepareP45Shot () =
let baseTick = M6Presentation.resolveStartTick (Some 12.0) false
let setTick (tick: int64) =
@@ -2255,6 +2339,14 @@ type LivingVillageGame() as this =
else this.DispatchMenuInput Confirm
elif menu.Page = Playing then
this.PrepareP65Shot()
+ elif p67ShotMode then
+ if menu.Page = MainMenu then
+ this.DispatchMenuInput Confirm
+ elif menu.Page = OccupationSelect then
+ if menu.Selected <> 0 then this.DispatchMenuInput Down
+ else this.DispatchMenuInput Confirm
+ elif menu.Page = Playing then
+ this.PrepareP67Shot()
elif p45ShotMode then
if menu.Page = MainMenu then
this.DispatchMenuInput Confirm
@@ -2733,6 +2825,8 @@ type LivingVillageGame() as this =
this.CaptureP64Shot()
if p65ShotMode && menu.Page = Playing then
this.CaptureP65Shot()
+ if p67ShotMode && menu.Page = Playing then
+ this.CaptureP67Shot()
if p45ShotMode && menu.Page = Playing then
this.CaptureP45Shot()
if p46ShotMode then
diff --git a/src/LivingVillage.Desktop/Interaction.fs b/src/LivingVillage.Desktop/Interaction.fs
index ba792d1..6c62661 100644
--- a/src/LivingVillage.Desktop/Interaction.fs
+++ b/src/LivingVillage.Desktop/Interaction.fs
@@ -719,7 +719,7 @@ module M5Interaction =
match occupationState.Today with
| None -> [ "今日暂无任务" ]
| Some task ->
- [ sprintf "%s:%s" (Occupation.taskNameOf task.TemplateId) (taskStateText task.State) ]
+ [ TaskRuntime.taskLine task (taskStateText task.State) ]
@ (match task.State with
| Occupation.Offered -> [ "回车:接受任务" ]
| _ -> [])
diff --git a/src/LivingVillage.Desktop/TaskRuntime.fs b/src/LivingVillage.Desktop/TaskRuntime.fs
index efc57f3..ce9bfbc 100644
--- a/src/LivingVillage.Desktop/TaskRuntime.fs
+++ b/src/LivingVillage.Desktop/TaskRuntime.fs
@@ -16,6 +16,20 @@ module TaskRuntime =
| Some(item, quantity) -> sprintf "%s +%s×%d" headline (Occupation.itemNameOf item) quantity
| None -> headline
+ // ---- P67 任务目标 UI(design §2.4-3 收口后的可见化)----
+ /// 带目标时的中文目标名:帮工 → 指定村民;翻土 → 自家地块。其余模板/无目标 → None。
+ let targetText (task: Occupation.DailyTask) : string option =
+ match task.TemplateId, task.TargetNpc, task.TargetTile with
+ | Occupation.HelpWork, Some(Sim.NpcId id), _ -> Some(sprintf "村民 %d" id)
+ | Occupation.TillSoil, _, Some _ -> Some "自家地块"
+ | _ -> None
+
+ /// 任务标题行:有目标时「模板:状态 → 目标」;无目标时与既有文案逐字节一致。
+ let taskLine (task: Occupation.DailyTask) (stateText: string) : string =
+ match targetText task with
+ | Some target -> sprintf "%s:%s → %s" (Occupation.taskNameOf task.TemplateId) stateText target
+ | None -> sprintf "%s:%s" (Occupation.taskNameOf task.TemplateId) stateText
+
let private completionMessage
(before: Occupation.DailyTask option)
(after: Occupation.DailyTask option)