dsh-piggy 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1348 -0
- package/LICENSE +32 -0
- package/README.md +322 -0
- package/THIRD-PARTY.md +31 -0
- package/assets/elder.svg +35 -0
- package/assets/pig-king-bathe.svg +38 -0
- package/assets/pig-king-eat.svg +45 -0
- package/assets/pig-king-pet.svg +45 -0
- package/assets/pig-king-play.svg +45 -0
- package/assets/pig-king-relaxed.svg +56 -0
- package/assets/pig-king-study.svg +45 -0
- package/assets/pig-king-trip.svg +45 -0
- package/assets/pig-king-work.svg +45 -0
- package/assets/pig-king.svg +56 -0
- package/assets/piglet.svg +30 -0
- package/client.js +3438 -0
- package/commands.js +252 -0
- package/cordis.patch.yml +15 -0
- package/core.js +11 -0
- package/data.js +10 -0
- package/index.js +68 -0
- package/package.json +72 -0
- package/packages/pet-core/package.json +21 -0
- package/packages/pet-core/src/core/activity.js +80 -0
- package/packages/pet-core/src/core/care.js +160 -0
- package/packages/pet-core/src/core/clock.js +122 -0
- package/packages/pet-core/src/core/constants.js +109 -0
- package/packages/pet-core/src/core/daily.js +204 -0
- package/packages/pet-core/src/core/diary.js +108 -0
- package/packages/pet-core/src/core/drops.js +82 -0
- package/packages/pet-core/src/core/effects.js +84 -0
- package/packages/pet-core/src/core/egg.js +120 -0
- package/packages/pet-core/src/core/evolution.js +90 -0
- package/packages/pet-core/src/core/growth.js +110 -0
- package/packages/pet-core/src/core/illness.js +235 -0
- package/packages/pet-core/src/core/interests.js +55 -0
- package/packages/pet-core/src/core/inventory.js +177 -0
- package/packages/pet-core/src/core/lines.js +157 -0
- package/packages/pet-core/src/core/migrate.js +226 -0
- package/packages/pet-core/src/core/profile.js +102 -0
- package/packages/pet-core/src/core/random.js +79 -0
- package/packages/pet-core/src/core/school.js +81 -0
- package/packages/pet-core/src/core/settlement.js +308 -0
- package/packages/pet-core/src/core/state.js +210 -0
- package/packages/pet-core/src/core/travel.js +58 -0
- package/packages/pet-core/src/core/upgrades.js +193 -0
- package/packages/pet-core/src/core/views.js +55 -0
- package/packages/pet-core/src/core/work.js +50 -0
- package/packages/pet-core/src/core.js +95 -0
- package/packages/pet-core/src/data/daily.js +121 -0
- package/packages/pet-core/src/data/drops.js +34 -0
- package/packages/pet-core/src/data/evolution.js +41 -0
- package/packages/pet-core/src/data/growth.js +72 -0
- package/packages/pet-core/src/data/illness.js +188 -0
- package/packages/pet-core/src/data/interests.js +39 -0
- package/packages/pet-core/src/data/jobs.js +150 -0
- package/packages/pet-core/src/data/life.js +88 -0
- package/packages/pet-core/src/data/lines.js +198 -0
- package/packages/pet-core/src/data/minutes.js +23 -0
- package/packages/pet-core/src/data/profile.js +60 -0
- package/packages/pet-core/src/data/school.js +99 -0
- package/packages/pet-core/src/data/shop.js +142 -0
- package/packages/pet-core/src/data/traits.js +42 -0
- package/packages/pet-core/src/data/travel.js +87 -0
- package/packages/pet-core/src/data.js +52 -0
- package/packages/pet-core/src/index.js +12 -0
- package/render.js +357 -0
- package/routes.js +201 -0
- package/scripts/build-client.mjs +100 -0
- package/scripts/typecheck.mjs +122 -0
- package/snapshot.js +368 -0
- package/src/client/art.js +29 -0
- package/src/client/constants.js +88 -0
- package/src/client/css-base.js +225 -0
- package/src/client/css-card.js +63 -0
- package/src/client/css-tabs.js +250 -0
- package/src/client/css-tiles.js +89 -0
- package/src/client/dom.js +33 -0
- package/src/client/effects.js +159 -0
- package/src/client/format.js +27 -0
- package/src/client/index.js +393 -0
- package/src/client/io.js +100 -0
- package/src/client/layout.js +103 -0
- package/src/client/normalize.js +352 -0
- package/src/client/panel.js +319 -0
- package/src/client/scene.js +113 -0
- package/src/client/storage.js +19 -0
- package/src/client/styles.js +13 -0
- package/src/client/tabs/bag.js +203 -0
- package/src/client/tabs/card.js +110 -0
- package/src/client/tabs/crown.js +59 -0
- package/src/client/tabs/dev.js +101 -0
- package/src/client/tabs/home.js +72 -0
- package/src/client/tabs/shop.js +78 -0
- package/src/client/tabs/status.js +223 -0
- package/src/client/tabs/study.js +128 -0
- package/src/client/tabs/travel.js +89 -0
- package/src/client/tabs/update.js +164 -0
- package/src/client/tabs/work.js +106 -0
- package/src/client/values.js +11 -0
- package/src/client/widgets.js +126 -0
- package/store/api.js +260 -0
- package/store/state-file.js +129 -0
- package/store.js +96 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,1348 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `dsh-pig`. Versions follow the plugin's own
|
|
4
|
+
`package.json`; the DSH runtime it targets is noted where it matters.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## [0.25.0] — 2026-10-01 · — 桌面版
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `apps/desktop/`:Electron 桌面版,双击出猪。复用插件的存档、结算和路由,不开端口;
|
|
12
|
+
透明置顶窗口只在猪和面板处接收点击。托盘:藏起来 / 开机自启 / 从 DSH 导入猪 / 退出。
|
|
13
|
+
- 桌面版主屏的 🔄 更新 App:从 GitHub Release 一键更新、挑版本、回退;游戏包校验 sha256,
|
|
14
|
+
换版本前备份存档,读不了当前存档的旧版本置灰。
|
|
15
|
+
- 发版流程 `.github/workflows/release.yml`:推 `v*` 标签自动测试并出游戏包、AppImage、Windows 安装包。
|
|
16
|
+
|
|
17
|
+
## [0.25.0] — 2026-10-01 · — 名字统一成 dsh-piggy
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- 路由 `/dsh-pig/*` → `/dsh-piggy/*`,默认存档目录 `$DSH_HOME/dsh-pig/` → `$DSH_HOME/dsh-piggy/`,
|
|
21
|
+
profile 层 id 也改成 `dsh-piggy`。
|
|
22
|
+
- 旧存档目录第一次启动时自动整个复制过去,旧目录改名为 `dsh-pig.moved-<时间>` 保留。
|
|
23
|
+
- 面板的本地设置(开合、位置、开发者模式)换了键名,仍会读旧键,不会重置。
|
|
24
|
+
|
|
25
|
+
## [0.25.0] — 2026-10-01 · — 加冕(改编自 PR #2,作者 1nuoiscute)
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- 加冕:长成后(成年 Lv40 + 三维各 20 + 本代打工 10 次)可以在主屏新的「👑 加冕」App 里加冕成猪猪王,
|
|
29
|
+
也可以一直当普通猪。只换样子,不加收益。形态做成表,以后会加别的形态。
|
|
30
|
+
- 猪猪王的 9 张立绘(待机、闭眼享受、吃、洗、玩、摸、打工、上学、旅行),按动作自动切换。
|
|
31
|
+
- `/pig crown [形态]` 命令。
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- 存档 v12:新字段 `form`。
|
|
35
|
+
|
|
36
|
+
## [0.25.0] — 2026-10-01 · — B9 主屏与居民卡
|
|
37
|
+
|
|
38
|
+
- 打开面板先是九宫格主屏(像动森手机):状态、居民卡、学习、打工、商店、旅行、背包各一格,点进去,左上角「‹」回来。底部图标栏不再显示。
|
|
39
|
+
- 新的「居民卡」:头像、名字、性别、等级称号、生日、星座、性格、口头禅、签名、收藏数。性格拆盒时随机,口头禅和签名可以改,猪说话时偶尔带上口头禅。
|
|
40
|
+
- 打工也改成方块:武力 / 魅力 / 智力 → 职业 → 点开看门槛和「出发」。
|
|
41
|
+
- 「在外面 / 生病 / 走了」的提示只在状态页显示,主屏的「状态」方块上挂小标签;和下面的内容拉开了间距。
|
|
42
|
+
- 修:猪出门时,面板下方的名字框会挤到猪身上。
|
|
43
|
+
|
|
44
|
+
## [0.25.0] — 2026-10-01 · — B8 方块界面
|
|
45
|
+
|
|
46
|
+
- 学习、商店、背包改成动森手机那样的彩色方块:第一层是大类(学段 / 货架 / 背包分类),点进去里面也是方块,左上角「‹」返回。截图见 `docs/screenshots/b8-*.png`。
|
|
47
|
+
- 锁住的学段变灰但能点进去看;等级不够的装扮变灰;背包空的分类变灰。
|
|
48
|
+
- 面板展开时 📅 签到不再压在图标栏上,挪到猪旁边。
|
|
49
|
+
|
|
50
|
+
## [0.25.0] — 2026-10-01 · — 界面体验修复
|
|
51
|
+
|
|
52
|
+
按用户 2026-10-01 的反馈修的 bug(**学习 / 商店 / 背包的排版保持原样**:用户先要过折叠、
|
|
53
|
+
再要过方块,看了都不满意,最后要求还原,两个版本都已撤掉):
|
|
54
|
+
|
|
55
|
+
- **点猪不再横跳**:签到气泡的 `@keyframes` 和猪的待机动画重名,覆盖后猪被 `translateX(-50%)`
|
|
56
|
+
推走半个身位,一播反应动画就跳回去再跳回来。
|
|
57
|
+
- **面板钉住自己的基准字号**:打工详情这类没写字号的框会继承宿主页面的 16px,比周围大一倍。
|
|
58
|
+
- **学习页选中的学段不再被 4 秒轮询顶回小学**:自动归位只在用户还没自己选过时生效。
|
|
59
|
+
- **签到气泡挂在猪上方**:折叠时原来和猪重叠 24px。
|
|
60
|
+
- **面板里能改猪的名字了**:「✏️ 称呼」改主人、「✏️ 名字」改猪;昵称不再印在面板上。
|
|
61
|
+
- **删掉解释性废话**:纸盒的「不用敲命令」、生病与墓碑的长说明、空背包/空家当的劝告。
|
|
62
|
+
|
|
63
|
+
## [0.25.0] — 2026-10-01 · — B6 台词
|
|
64
|
+
|
|
65
|
+
- 24 个场景、90 多句台词(文案见 `docs/tasks/numbers/B6-lines.md`):吃撑、打工回来/累了、上完课、毕业、旅行回来、长大、复活等都会说话。
|
|
66
|
+
- 闲着每 20–40 分钟冒一句,先说需要什么(饿/脏/孤单),不需要才闲聊;离开半小时以上再打开会打招呼。
|
|
67
|
+
- 状态页:「🙋 叫你「主人」 改」可以改称呼;「🔔 免打扰」开了不闲聊、不弹日常消息,生病和死亡照样提醒。
|
|
68
|
+
- 学习页:「🎯 兴趣」成了学段旁边的一个按钮。
|
|
69
|
+
- 调整:病得慢一点(饿、脏各 3%/h),三维报酬加成降到每点 1/150 且不再缩短工时。
|
|
70
|
+
|
|
71
|
+
## [0.25.0] — 2026-10-01 · — B2 成长 · B3 疾病 · B4 学习→职业
|
|
72
|
+
|
|
73
|
+
数值全部照 `docs/tasks/numbers/` 里用户 2026-10-01 确认的单子。存档 8 → 11,每一级升级前都会原样备份。
|
|
74
|
+
|
|
75
|
+
### B2 成长
|
|
76
|
+
- 成长值(存档里的 `xp`)按猪时间自己长:每小时 +100,乘照顾系数(心情、饿脏、健康)。
|
|
77
|
+
- 等级曲线 122 × L²,满级 60(约半年)。形态按等级:幼年 Lv1 / 青年 Lv10 / 成年 Lv40。
|
|
78
|
+
- **去掉老年阶段和老死**,猪只会因为意外(病到最后一期)死掉。
|
|
79
|
+
- 陪主人干活每天最多额外 +300 成长;打工/旅行每小时 +25,上课每节 +40。
|
|
80
|
+
- 拆纸盒时定性别(♂/♀)。
|
|
81
|
+
|
|
82
|
+
### B3 疾病
|
|
83
|
+
- 五条链(感冒 / 咳嗽 / 肠胃 / 头晕 / 皮肤),每一期一味专用药(30/70/140/260),百草丹 500 包治百病,还魂丹 800。
|
|
84
|
+
- 发病改为按条件的每小时概率:饿 → 感冒,脏 → 咳嗽(很脏 → 皮肤),心情差或连续打工上课 → 头晕,吃撑 → 肠胃。
|
|
85
|
+
- 吃错药病情立刻加重一级;看医生按药价 × 1.5 直接治好。旧的四种通用药按新价退金币。
|
|
86
|
+
|
|
87
|
+
### B4 学习 → 职业
|
|
88
|
+
- 九门课(语文 数学 政治 音乐 艺术 礼仪 体育 劳技 武术)各算各的课时;第 9 / 20 / 40 / 95 节毕业,必得 3 件礼物。
|
|
89
|
+
- 33 种职业(原版 18 + 新增 15),门槛是等级 + 课时(+ 兴趣证书);三维只影响报酬。
|
|
90
|
+
- 兴趣课上满 5 次拿证;打工、上课回来会随机带东西。
|
|
91
|
+
- 旧的 23 门课按对照表并进九门课的课时;正在打的旧工作按旧报酬结算。
|
|
92
|
+
|
|
93
|
+
### Documentation
|
|
94
|
+
- README 截图使用仓库相对路径;补充独立克隆、源码构建及 Windows PowerShell 入门。
|
|
95
|
+
- 开发目录说明适配 packages/pet-core,构建工具固定为已验证版本。
|
|
96
|
+
|
|
97
|
+
### Verification(文档)
|
|
98
|
+
- 本地链接、构建、类型检查及完整自动测试通过;客户端生成产物保持与上游一致。
|
|
99
|
+
|
|
100
|
+
## [0.25.0] — 2026-10-01 · — 批次 0 框架
|
|
101
|
+
|
|
102
|
+
### Changed(内部)
|
|
103
|
+
- 领域层抽成 `packages/pet-core`(`@dsh-piggy/core`,零依赖),DSH 插件和以后的独立版共用;根目录 `core.js` / `data.js` 改为再导出,导入路径不变。
|
|
104
|
+
- 结算改为分段分步:一段空白切成「在外到活动结束」+「在家」,每 5 分钟一步推进。
|
|
105
|
+
- 随机数种子存进存档(`state.seed`),领域层不再调用 `Math.random()`。
|
|
106
|
+
- 存档逐级升级框架(`core/upgrades.js`),升级前原样备份为 `state.json.v<旧版本>-backup-<时间>`。存档版本 7 → 8。
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
- 台词框架:13 个场景、`[主人]` 称呼、气泡里的回复按钮(回复一次加一点心情)。喂食/洗澡/玩耍/摸摸会说话。文案是样例,待 B6 审定。
|
|
110
|
+
- 任务卡与数值确认单:`docs/tasks/`。
|
|
111
|
+
|
|
112
|
+
### Fixed
|
|
113
|
+
- 没拆的纸盒吃到经验后,重启会被当成已孵化的猪。
|
|
114
|
+
- 15 分钟零工 + 关机一整晚,整晚都按「在外」算:不掉到保底线以下、不会生病,工钱还盖着重开面板那一刻的时间。现在活动在结束那一刻结算。
|
|
115
|
+
- 同一时刻的多条消息(如「病情加重」+「走了」)只显示第一条。
|
|
116
|
+
|
|
117
|
+
### Behaviour change
|
|
118
|
+
- 关掉 DSH 期间没人照顾,猪会在中途真实地生病、病情继续发展(以前只在重开那一刻才开始算)。生病期间不再累积「得新病」的风险。
|
|
119
|
+
|
|
120
|
+
## [0.24.0] — 2026-09-30
|
|
121
|
+
|
|
122
|
+
### Added
|
|
123
|
+
- **调试页显示构建版本**:「🔧 开发者模式 · 构建 v0.24.0 · Ctrl+Shift+D 关闭」。
|
|
124
|
+
DSH 是在**启动时**组装客户端 bundle 的,改完代码不重启就还是旧界面 ——
|
|
125
|
+
以后"我现在看的是哪一版"直接读这一行,不用猜。
|
|
126
|
+
|
|
127
|
+
### Changed(对外)
|
|
128
|
+
- **插件描述不再宣称"复刻"**:只保留"玩法参考经典电子宠物"的说法,元数据里
|
|
129
|
+
也去掉了第三方的品牌词。新增 [THIRD-PARTY.md](THIRD-PARTY.md),逐项列明参考
|
|
130
|
+
资料、运行时依赖、美术来源与许可,并保留商标声明。
|
|
131
|
+
|
|
132
|
+
### Fixed
|
|
133
|
+
- **存档损坏不再让猪静默消失**:以前 `load()` 是裸 `catch`,文件一坏就当作"没有猪",
|
|
134
|
+
下一次写入还会把坏文件覆盖掉。现在会保留一份 `state.json.corrupt-<时间>`、
|
|
135
|
+
日志说清原因,原文件不动。
|
|
136
|
+
|
|
137
|
+
### Changed(内部,界面无变化)
|
|
138
|
+
- 客户端源码移到 `src/client/`,`client.js` 改为 esbuild 产物;`npm run build` 生成,
|
|
139
|
+
`test/bundle.test.js` 守住产物新鲜度。详见 [docs/REFACTOR-PLAN.md](docs/REFACTOR-PLAN.md)。
|
|
140
|
+
- 新增 [docs/CONVENTIONS.md](docs/CONVENTIONS.md)(项目版编码规范)。
|
|
141
|
+
- 分层拆分(均保留同名 barrel,导入路径零改动):`data.js` → `data/` 9 个模块、
|
|
142
|
+
`core.js` → `core/` 15 个模块、`index.js` → `snapshot/commands/routes`、
|
|
143
|
+
`store.js` → `store/{api,state-file}`。公开导出面逐项比对无变化。
|
|
144
|
+
- 领域层不再读系统时间(`nowMs` 一律作参数);代码注释去掉 emoji;
|
|
145
|
+
新增静态守卫(领域层时间、注释 emoji、文件 400 行上限、发布 files 覆盖)。
|
|
146
|
+
- 新增 `npm run typecheck`(`tsc --noEmit --checkJs`,不进构建、不加依赖)与
|
|
147
|
+
静态守卫;源码全部带 `// @ts-check`,当前**零类型错误**。
|
|
148
|
+
- 客户端源码按职责拆成 `styles/constants/values/normalize/storage/dom/scene/
|
|
149
|
+
effects/layout/panel/io` 与 `tabs/*`,由 esbuild 打包;界面渲染结果与拆分前
|
|
150
|
+
逐页签、逐交互(拖拽、开关、装扮)比对一致。
|
|
151
|
+
|
|
152
|
+
### Verification
|
|
153
|
+
- `node --test`:**175 / 175 通过**(新增:产物新鲜度、单文件契约、版本字段、
|
|
154
|
+
存档损坏保留现场 5 项、领域层时间 / 注释 emoji / 文件行数三条静态守卫)。
|
|
155
|
+
|
|
156
|
+
## [0.23.0] — 2026-09-30
|
|
157
|
+
|
|
158
|
+
按你的四条反馈改。
|
|
159
|
+
|
|
160
|
+
### Changed
|
|
161
|
+
- **面板不再讲道理**:删掉「等级不会因为猪走了而清零 —— 领养新猪时会继承」
|
|
162
|
+
「再过 N 天就长成下一阶段了」「去「学习」上课就能涨这些属性」「不用解锁,想学就学」。
|
|
163
|
+
这些是设计说明,不该出现在界面里。
|
|
164
|
+
- **打工解锁只写需求**:「🔒 需要 💪 武力 16」,不再附「(你现在 9)」;
|
|
165
|
+
解锁后属性那行也从「✨ 魅力 0 · 去上课就能涨」缩成「✨ 魅力 0」。
|
|
166
|
+
- **时间倍率搬进「调试」页**:现在是调试页里的「时间」分组(×1 真实 / ×12 / ×30 / ×60),
|
|
167
|
+
状态页彻底没有它。
|
|
168
|
+
|
|
169
|
+
### Added
|
|
170
|
+
- **装扮真的穿在猪身上了**:猪有 6 个固定点位 —— 头 / 脸 / 脖子 / 身子 / 背后 / 脚,
|
|
171
|
+
每个点位同时只挂一件(戴王冠会自己把草帽摘掉)。位置全部写在 client.js 的
|
|
172
|
+
`.dp-slot[data-slot="…"]` 里,**以后换成真立绘只改那几行偏移,逻辑和存档都不用动**。
|
|
173
|
+
背包里每件写清点位(「脖子 · 脖子上暖乎乎的」)。
|
|
174
|
+
- **调试页「🎁 一键拿齐」**:消耗品各 20、全部装扮、金币 99999。新路由 `giveAll`。
|
|
175
|
+
|
|
176
|
+
### Removed
|
|
177
|
+
- 名字牌上重复显示装扮的那串 emoji(现在挂在猪身上了,没必要写两遍)。
|
|
178
|
+
|
|
179
|
+
### Verification
|
|
180
|
+
- `node --test`:**164 / 164 通过**。
|
|
181
|
+
- 浏览器复查:状态页没有讲解文字也没有时间倍率;调试页有「时间」和「一键拿齐」;
|
|
182
|
+
围巾出现在 `.dp-slot[data-slot="neck"]` 且落在猪的包围盒内;背包显示「脖子 · 脖子上暖乎乎的」。
|
|
183
|
+
|
|
184
|
+
## [0.22.0] — 2026-09-30
|
|
185
|
+
|
|
186
|
+
按你的反馈砍回简版。
|
|
187
|
+
|
|
188
|
+
### Removed
|
|
189
|
+
- **体力 / 才艺 / 审美 / 头脑 这四条「技能」全部删掉。** 它们只是 武力 / 魅力 / 智力
|
|
190
|
+
换了个名字:状态页那一栏、技能等级、百分比、上限,以及"用技能抵扣打工门槛"的整套逻辑
|
|
191
|
+
全部回退。现在只有 🧠 智力 / ✨ 魅力 / 💪 武力 三条。
|
|
192
|
+
|
|
193
|
+
### Changed
|
|
194
|
+
- **时间倍率(×1 / ×12 / ×30 / ×60)挪进开发者模式**(Ctrl+Shift+D),普通用户看不到 ——
|
|
195
|
+
那是调试用的,不该让人为了"猪长得慢"去点它。
|
|
196
|
+
- **兴趣改成「学习」页里的一栏可学课程**:📷 摄影 / 💻 编程 / 💃 跳舞 / 🏋 健身。
|
|
197
|
+
不用解锁、可以反复学,学一次直接把 +2 加到对应的那一条属性上;
|
|
198
|
+
右上角直接写「30 分钟 · 40 🪙 · ✨魅力 +2」。
|
|
199
|
+
不再是状态页里一栏看不懂的被动技能条。
|
|
200
|
+
|
|
201
|
+
### Verification
|
|
202
|
+
- `node --test`:**160 / 160 通过**(删掉 6 个技能测试,新增 5 个兴趣/开发者模式测试)。
|
|
203
|
+
- 浏览器复查:状态页没有技能栏、没有时间倍率按钮;学习页「🎯 兴趣」四条正常;无文案截断。
|
|
204
|
+
|
|
205
|
+
## [0.21.0] — 2026-09-30
|
|
206
|
+
|
|
207
|
+
批次 4 之二:**商店 21 → 45 件 + 装扮(家当)**。ROADMAP 的四批改造到此做完。
|
|
208
|
+
|
|
209
|
+
### Added
|
|
210
|
+
- **货架扩容到 45 件**:食物 6→10、洗浴 5→8、玩具 5→10,药品 4 件、复活 1 件不变。
|
|
211
|
+
- **12 件装扮(新货架「家当」)**:红围巾 Lv.1 → 翅膀 Lv.16,价格 80 → 8000。
|
|
212
|
+
|
|
213
|
+
| 等级 | 装扮 |
|
|
214
|
+
|---|---|
|
|
215
|
+
| Lv.1–3 | 红围巾 🧣 · 草帽 👒 · 墨镜 🕶 |
|
|
216
|
+
| Lv.4–7 | 背带裤 👖 · 领结 🎀 · 雨靴 🥾 · 披风 🦸 |
|
|
217
|
+
| Lv.8–13 | 花环 💐 · 礼帽 🎩 · 项链 📿 · 王冠 👑 |
|
|
218
|
+
| Lv.16 | 翅膀 🪽 |
|
|
219
|
+
|
|
220
|
+
- **穿上 / 脱下**:背包页新增「👕 家当 x/12 穿着中」,每件一行;穿着的装扮显示在
|
|
221
|
+
名字牌上(`猪猪 Lv.3 · 成年猪 · 🧣👑`)。新路由 `wear`。
|
|
222
|
+
|
|
223
|
+
### Changed
|
|
224
|
+
- 商店把**消耗品**和**家当**分开:消耗品照旧计数(×N)、买不起的淡掉;
|
|
225
|
+
家当不计数、不可重复购买、按等级解锁 —— 等级不够的格子写「🔒 Lv.13」,
|
|
226
|
+
已拥有的写「已拥有」(虚线框、按钮禁用)。
|
|
227
|
+
- 背包的物品计数不再包含装扮(它不是拿来用的),对装扮点「使用」会被诚实拒绝
|
|
228
|
+
(`not-consumable`)。
|
|
229
|
+
|
|
230
|
+
### Migration / 数据
|
|
231
|
+
- 存档新增两个字段:`dress`(已拥有)与 `worn`(正在穿)。旧存档没有它们 →
|
|
232
|
+
空数组,不影响任何已有内容;手工改坏的存档(比如把药品塞进 `dress`)在读取时被丢掉,
|
|
233
|
+
而且**只有已拥有的才能穿上**。
|
|
234
|
+
- 这次没有升 `STATE_VERSION`(仍是 7):两个字段都是可选的,`migrate` 会补默认值。
|
|
235
|
+
|
|
236
|
+
### Verification
|
|
237
|
+
- `node --test`:**161 / 161 通过**(新增:45 件货架与六层分组、装扮按等级购买且只能买一次、
|
|
238
|
+
穿上/脱下、药品不能穿、损坏存档被清洗、`wear` 路由、商店/背包/名字牌三处渲染)。
|
|
239
|
+
- `tools/preview.html` 真实浏览器复查:装扮货架(已拥有的虚线框、🔒 Lv.4…Lv.16)、
|
|
240
|
+
背包「家当 1/12 穿着中」与穿上/脱下、名字牌上的 🧣、无文案截断。
|
|
241
|
+
|
|
242
|
+
## [0.20.0] — 2026-09-30
|
|
243
|
+
|
|
244
|
+
批次 4 之一:**旅行目的地扩容 + 纪念品能打开**。
|
|
245
|
+
|
|
246
|
+
纪念品以前是字符串数组(`['贝壳']`),列出来就完了,点不了、卖不掉、没有出处。
|
|
247
|
+
现在每一件都是带稀有度和故事的物件。
|
|
248
|
+
|
|
249
|
+
### Added
|
|
250
|
+
- **旅行目的地 4 → 7**:郊游 / 名山大川 / 泡温泉 / 看海 / 古镇 / 出国 / 看极光。
|
|
251
|
+
目的地行直接写「可带回 🔵稀有」,远的地方一眼看出值不值。
|
|
252
|
+
- **25 件纪念品**,每件带 `key / emoji / 名字 / 稀有度 / 故事`:
|
|
253
|
+
|
|
254
|
+
| 稀有度 | 卖价 | 例子 |
|
|
255
|
+
|---|---|---|
|
|
256
|
+
| ⚪ 普通 | 60 🪙 | 松果、海盐、温泉蛋 |
|
|
257
|
+
| 🔵 稀有 | 320 🪙 | 一枚海螺(「贴在耳朵上能听见浪声」)、异国邮票、小灯笼 |
|
|
258
|
+
| 🟡 传说 | 1600 🪙 | 漂流瓶(「瓶子里有张潮湿的纸条」)、极光照片、紫砂壶 |
|
|
259
|
+
|
|
260
|
+
- **点开看故事**:旅行页点纪念品展开卡片 —— 名字、稀有度、来自哪里,
|
|
261
|
+
以及猪带回来时说的那句话(「在海边捡到一枚海螺,贴在耳朵上能听见浪声。」),
|
|
262
|
+
下面就是「卖掉 +320 🪙」。
|
|
263
|
+
- **卖纪念品**:新路由 `sell`,按稀有度结账;没有的东西诚实拒绝(`not-owned`),不会白给钱。
|
|
264
|
+
|
|
265
|
+
### Changed
|
|
266
|
+
- 纪念品的稀有度是**表的属性**,不是抽卡:远的目的地带回来的档次更高,
|
|
267
|
+
和「轮换是确定性的」这条老规矩一致,所以整条链路可测。
|
|
268
|
+
- 长行程的时长按小时显示(`720 分钟` → `12 小时`)——292px 的面板里这样才放得下稀有度提示。
|
|
269
|
+
|
|
270
|
+
### Migration
|
|
271
|
+
- 存档版本 **6 → 7**。旧存档里的字符串纪念品(`"贝壳"`)会包成普通纪念品:
|
|
272
|
+
照样列出来、照样能卖 60 金币,故事位置写明「旧版本带回来的」。
|
|
273
|
+
|
|
274
|
+
### Verification
|
|
275
|
+
- `node --test`:**156 / 156 通过**(新增:纪念品是对象且有故事、轮换可达每一件、
|
|
276
|
+
卖价按稀有度、旧字符串纪念品可卖、路由拒绝未拥有的、客户端故事卡与卖掉按钮)。
|
|
277
|
+
- `tools/preview.html` 真实浏览器复查:7 个目的地、稀有度提示、点开故事卡、
|
|
278
|
+
「卖掉 +320 🪙」、旧字符串纪念品走降级卡片、无文案截断、矮窗口下猪仍在屏幕内。
|
|
279
|
+
|
|
280
|
+
## [0.19.0] — 2026-09-30
|
|
281
|
+
|
|
282
|
+
批次 3 之三:**兴趣技能**。批次 3 到此完整(工种门槛 + 七级学段 + 兴趣技能)。
|
|
283
|
+
|
|
284
|
+
### Added
|
|
285
|
+
- **四个兴趣技能**,全部从「课外」四门课长出来,**等级就是那门课上过几次** ——
|
|
286
|
+
没有单独的存档字段,重复上课就是升级:
|
|
287
|
+
|
|
288
|
+
| 课外课 | 技能 | 效果 |
|
|
289
|
+
|---|---|---|
|
|
290
|
+
| ⚽ 足球 | 💪 体力 | 体力活(快递 / 搬砖 / 领班)时长 −5%/级,上限 −25% |
|
|
291
|
+
| 🎹 钢琴 | 🎤 才艺 | 魅力类工作报酬 +5%/级(上限 +25%),并抵扣街头卖艺门槛 2 点/级 |
|
|
292
|
+
| 🎨 画画 | 🖼 审美 | 旅行心情 +10%/级,上限 +50% |
|
|
293
|
+
| ♟ 围棋 | ♟ 头脑 | 上课时长 −5%/级(上限 −25%),并抵扣家教门槛 2 点/级 |
|
|
294
|
+
|
|
295
|
+
- **技能能开工作**:才艺 4 级正好顶平街头卖艺的「魅力 8」,头脑 5 级顶平家教的「智力 10」。
|
|
296
|
+
抵扣写在锁定行下面(「🎤 才艺 抵扣了 2 点门槛」)—— 不然变小的数字看起来像 bug。
|
|
297
|
+
- 状态页新增 **「🎯 本事」** 一栏:四个技能全列出来(0 级写「还没练」),
|
|
298
|
+
写清效果和「上哪门课升级」。
|
|
299
|
+
|
|
300
|
+
### Changed
|
|
301
|
+
- 结算分工明确:**体力只减免体力活,才艺只加魅力活的报酬**,
|
|
302
|
+
不会出现"练钢琴让搬砖更快"这种事;头脑缩短的是上课时长,不是工时。
|
|
303
|
+
|
|
304
|
+
### Verification
|
|
305
|
+
- `node --test`:**150 / 150 通过**(新增 6 个:等级来自课外课且效果有上限、体力只作用于体力活、
|
|
306
|
+
才艺只作用于魅力活、头脑缩短课堂、审美提升旅行心情、技能抵扣门槛后拒绝报的是折后数字)。
|
|
307
|
+
- `tools/preview.html` 真实浏览器复查:状态页「本事」四条正常(含 0 级的「还没练」)、
|
|
308
|
+
工作页显示抵扣行、街头卖艺从锁定变可出发、无文案截断。
|
|
309
|
+
|
|
310
|
+
## [0.18.0] — 2026-09-30
|
|
311
|
+
|
|
312
|
+
批次 3 之二:**七级学段 + 按科目解锁**。
|
|
313
|
+
|
|
314
|
+
之前只有三个学段(小学 / 大学 / 研究生),而且解锁条件是「上一级上够 9 节课」——
|
|
315
|
+
一个数字。现在一门课在哪一级上、上过几次,都有账。
|
|
316
|
+
|
|
317
|
+
### Added
|
|
318
|
+
- **七级学段**,从幼儿园一路到研究生:
|
|
319
|
+
|
|
320
|
+
| 学段 | 科目数 | 单课时长 | 学费 | 属性 | 解锁条件 |
|
|
321
|
+
|---|---|---|---|---|---|
|
|
322
|
+
| 🧸 幼儿园 | 3 | 15 分 | 20 | +1 | 无 |
|
|
323
|
+
| 🎨 课外 | 4 | 20 分 | 30 | +1 | 幼儿园 3 门各一次 |
|
|
324
|
+
| 📚 小学 | 6 | 40 分 | 60 | +1 | 课外 4 门各一次 |
|
|
325
|
+
| 🏫 中学 | 7 | 1 小时 | 140 | +2 | 小学 6 门各一次 |
|
|
326
|
+
| 🎓 高中 | 8 | 2 小时 | 300 | +3 | 中学 7 门各一次 |
|
|
327
|
+
| 🏛 大学 | 9 | 4 小时 | 700 | +4 | 高中 8 门各一次 |
|
|
328
|
+
| 🔬 研究生 | 9 | 8 小时 | 1600 | +6 | 大学 9 门各一次 |
|
|
329
|
+
|
|
330
|
+
合计 **46 节课**(3+4+6+7+8+9+9)。
|
|
331
|
+
- **23 门科目**:唱歌 / 涂鸦 / 认字 / 足球 / 钢琴 / 画画 / 围棋 / 语文 / 数学 / 英语 /
|
|
332
|
+
科学 / 体育 / 美术 / 历史 / 地理 / 物理 / 化学 / 生物 / 政治 / 信息技术 /
|
|
333
|
+
哲学 / 经济 / 工程。高级学段重上低级科目时给得更多(语文:小学 +1、大学 +4)。
|
|
334
|
+
|
|
335
|
+
### Changed
|
|
336
|
+
- **解锁条件从「数够课」改成「念完每一门」**:新增 `coursesByStage[学段][科目]`。
|
|
337
|
+
七级学段共用科目名(语文在小学/中学/高中都教),所以"上过 9 节课"根本说明不了
|
|
338
|
+
小学的六门课上没上全。面板按选中学段只列这一级的课,并显示「本级上过 N 次」。
|
|
339
|
+
- **科目不属于该学段会被拒绝**(`wrong-stage`),而不是静默扣学费:幼儿园没有物理。
|
|
340
|
+
- 学段按钮不再把学费挤在标签里(七级排两行),学费挪到下面的说明行。
|
|
341
|
+
|
|
342
|
+
### Migration
|
|
343
|
+
- 存档版本 **5 → 6**。旧存档只记了「每级上过几节课」,科目无从还原,
|
|
344
|
+
所以按阶梯重建:**某级有课,说明它下面每一级都念过**;该级本身按旧的节数
|
|
345
|
+
从课表前面开始记。旧版「小学 9 节」= 新版小学 6 门全过,中学照常解锁 ——
|
|
346
|
+
已经念上去的猪不会被打回幼儿园。
|
|
347
|
+
|
|
348
|
+
### Verification
|
|
349
|
+
- `node --test`:**142 / 142 通过**(新增:七级阶梯门槛、跨学段科目拒绝、按科目记课、
|
|
350
|
+
旧存档重建、同一科目高级学段给得更多)。
|
|
351
|
+
- `tools/preview.html` 真实浏览器复查:7 个学段按钮排成 4+3 两行、切换学段时课程网格
|
|
352
|
+
跟着换(小学 6 门 / 高中 8 门)、锁定学段写明「🔒 要先念完中学 7 门课各上一次(3/7)」、
|
|
353
|
+
矮窗口(900×420)下内容可滚动且猪仍在屏幕内、科目文案无截断。
|
|
354
|
+
|
|
355
|
+
## [0.17.0] — 2026-09-30
|
|
356
|
+
|
|
357
|
+
批次 3 之一:**打工门槛 + 十个工种**。
|
|
358
|
+
|
|
359
|
+
之前只有 3 份工作,而且**一个门槛都没有** —— 智力 0 和智力 40 能干的活完全一样,
|
|
360
|
+
「学习」这一页等于白做。这一版把学习和打工接上了。
|
|
361
|
+
|
|
362
|
+
### Added
|
|
363
|
+
- **每个工种有三条轴的属性门槛**(🧠 智力 / ✨ 魅力 / 💪 武力):
|
|
364
|
+
|
|
365
|
+
| 工作 | 门槛 | 时长 | 报酬 |
|
|
366
|
+
|---|---|---|---|
|
|
367
|
+
| 🧹 打零工 | 无 | 15 分 | 30 |
|
|
368
|
+
| 🍽 端盘子 | 魅力 2 · 武力 2 | 30 分 | 70 |
|
|
369
|
+
| 🚚 送快递 | 武力 4 | 1 小时 | 150 |
|
|
370
|
+
| 🧱 搬砖 | 武力 8 | 1.5 小时 | 260 |
|
|
371
|
+
| 🏗 工地领班 | 魅力 4 · 武力 16 | 3 小时 | 700 |
|
|
372
|
+
| 🎤 街头卖艺 | 魅力 8 | 1 小时 | 200 |
|
|
373
|
+
| 📚 家教 | 智力 10 | 2 小时 | 480 |
|
|
374
|
+
| 💼 上班 | 智力 14 · 魅力 6 | 4 小时 | 900 |
|
|
375
|
+
| 🏢 部门主管 | 智力 22 · 魅力 10 | 6 小时 | 2200 |
|
|
376
|
+
| 🔬 研究员 | 智力 32 | 8 小时 | 4000 |
|
|
377
|
+
|
|
378
|
+
- **没资格时给的是缺口,不是灰按钮**:面板写「🔒 需要 🧠 智力 14(你现在 12)」,
|
|
379
|
+
多轴不够就把每一轴都列出来,下面再写一句「去「学习」上课就能涨这些属性」。
|
|
380
|
+
命令行拒绝同样说明差多少(`underqualified` → `missing[]`)。
|
|
381
|
+
|
|
382
|
+
### Changed
|
|
383
|
+
- 门槛**在猪出门前**判定:不够格不会扣饱食度、不会进入打工状态,拒绝是干净的。
|
|
384
|
+
- `trait` 从「这份工作靠什么属性」变成「这份工作的主属性」:门槛可以要两轴,
|
|
385
|
+
但报酬加成和时长减免仍然只由主属性算(魅力打工的猪不会因为武力低而少赚)。
|
|
386
|
+
|
|
387
|
+
### Fixed
|
|
388
|
+
- 老版宿主(没有 `qualified` 字段)在新客户端上**不会把所有工作锁死** ——
|
|
389
|
+
缺字段一律当作「有资格」。反向默认会在版本错配时把整个打工页变成 10 个「没资格」。
|
|
390
|
+
|
|
391
|
+
### Verification
|
|
392
|
+
- `node --test`:**140 / 140 通过**(新增 6 个:门槛拒绝、缺轴清单、双轴、门槛出门前判定、
|
|
393
|
+
客户端锁定行、老宿主不锁死)。
|
|
394
|
+
- `tools/preview.html` 真实浏览器复查:10 行工作、5 行带锁,矮窗口(900×420)下
|
|
395
|
+
内容可滚动且猪仍在屏幕内。
|
|
396
|
+
|
|
397
|
+
## [0.16.0] — 2026-09-30
|
|
398
|
+
|
|
399
|
+
批次 2:**时间尺度 + 双轴**。这是地基,后面的内容都挂在它上面。
|
|
400
|
+
|
|
401
|
+
### Changed
|
|
402
|
+
- **年龄对齐现实:一生 8 个月。** 之前是 14 天,跟现实差得太远。
|
|
403
|
+
|
|
404
|
+
| 形态 | 之前 | 现在 |
|
|
405
|
+
|---|---|---|
|
|
406
|
+
| 小猪 | 0–1 天 | **0–1 个月** |
|
|
407
|
+
| 青年猪 | 1–3 天 | **1–3 个月** |
|
|
408
|
+
| 成年猪 | 3–7 天 | **3–6 个月** |
|
|
409
|
+
| 老年猪 | 7–14 天 | **6–8 个月** |
|
|
410
|
+
| 🪦 墓碑 | 第 14 天 | **第 8 个月** |
|
|
411
|
+
| 👻 灵魂 | 死后 1 天 | 死后 1 天(不变) |
|
|
412
|
+
|
|
413
|
+
- **年龄改成累计「猪时间」,不是墙上时钟。** `state.ageMs` 每小时累加
|
|
414
|
+
`经过时间 × 倍率`。这样**改倍率只影响以后**,不会让猪因为你调了倍率
|
|
415
|
+
就突然从幼崽跳到老年。
|
|
416
|
+
|
|
417
|
+
- **时间倍率可调**(状态页四个按钮):
|
|
418
|
+
|
|
419
|
+
| 倍率 | 一生 | 小猪→青年 |
|
|
420
|
+
|---|---|---|
|
|
421
|
+
| **×1(默认)** | 8 个月 | 1 个月 |
|
|
422
|
+
| ×12 | 20 天 | 2.5 天 |
|
|
423
|
+
| ×30 | 8 天 | 1 天 |
|
|
424
|
+
| ×60 | 4 天 | 12 小时 |
|
|
425
|
+
|
|
426
|
+
### Added
|
|
427
|
+
- **第二条轴:等级。** 年龄是身体(会老会死),等级是经历(**永不清零**)。
|
|
428
|
+
|
|
429
|
+
曲线 `xpForLevel(n) = 20n(n−1)`,**无上限**:
|
|
430
|
+
|
|
431
|
+
| 等级 | 所需 xp | 称号 |
|
|
432
|
+
|---|---|---|
|
|
433
|
+
| 1 | 0 | 🌱 新来的 |
|
|
434
|
+
| 5 | 400 | 🙂 熟面孔 |
|
|
435
|
+
| 10 | 1800 | 🤝 老伙计 |
|
|
436
|
+
| 20 | 7600 | 🏠 镇宅之猪 |
|
|
437
|
+
| 35 | 23800 | 📣 十里八乡有名 |
|
|
438
|
+
| 50 | 49000 | 🌟 传说 |
|
|
439
|
+
| 80 | 126400 | 👑 神话 |
|
|
440
|
+
|
|
441
|
+
- **领养新猪会继承等级、学历、三维和收藏。** 这是双轴设计的关键:
|
|
442
|
+
**身体会死,历史不会。** 老死不再是「进度清零」,而是换一只猪接着养。
|
|
443
|
+
|
|
444
|
+
### Fixed
|
|
445
|
+
- 调试补丁的 `ageDays` 只设了 `bornAt`,没设 `ageMs` —— 年龄改成累计之后,
|
|
446
|
+
这个按钮就失灵了。现在两个一起设。
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## [0.15.0] — 2026-09-30
|
|
451
|
+
|
|
452
|
+
改造计划的第一批(手感 + 商店)。完整计划见 [docs/ROADMAP.md](docs/ROADMAP.md)。
|
|
453
|
+
|
|
454
|
+
### Added
|
|
455
|
+
- **小猪大了一圈。** 40px 在面板里太小了,整套尺寸重排:
|
|
456
|
+
|
|
457
|
+
| 形态 | 之前 | 现在 |
|
|
458
|
+
|---|---|---|
|
|
459
|
+
| 📦 纸盒 | 58 | 58 |
|
|
460
|
+
| 小猪 | 40 | **54** |
|
|
461
|
+
| 青年猪 | 48 | **60** |
|
|
462
|
+
| 中年猪 | 62 | **68** |
|
|
463
|
+
| 老年猪 | 56 | **62** |
|
|
464
|
+
| 🪦 墓碑 | 52 | **56** |
|
|
465
|
+
|
|
466
|
+
- **摸摸有 10 句台词了。** 之前只有「好舒服…」,点两下就腻。
|
|
467
|
+
现在每次随机抽一句(再摸摸~ / 嘿嘿 / 呼噜呼噜… / 这里这里! / (眯起眼睛) …)。
|
|
468
|
+
- **戳猪会「扁」一下。** `scale(1.16, .74)` 压扁再弹回来,420ms —— 短到连点也跟得上。
|
|
469
|
+
|
|
470
|
+
### Fixed
|
|
471
|
+
- **连点摸头只有第一下有反应。** `react()` 每次都把 `data-react` 设成同一个值,
|
|
472
|
+
而**重新赋同样的值不会重启动画** —— 所以动画只播一次。
|
|
473
|
+
现在先摘掉属性、`void pig.offsetWidth` 强制重排、再挂回去,**每一下都从头播**。
|
|
474
|
+
|
|
475
|
+
### Changed
|
|
476
|
+
- **商店从竖列表改成 3 列格子。** 292px 宽的竖列表一屏只能看 3 件,21 件要滚很久;
|
|
477
|
+
格子布局一屏 9 件,货架标题横跨整行。
|
|
478
|
+
|
|
479
|
+
```
|
|
480
|
+
🍎 食物
|
|
481
|
+
┌────┬────┬────┐
|
|
482
|
+
│ 🍎 │ 🍞 │ 🍖 │ emoji / 名字 / 价格
|
|
483
|
+
│苹果│面包│骨头│ 持有数做成右上角角标
|
|
484
|
+
│ 6 │ 10 │ 15 │
|
|
485
|
+
└────┴────┴────┘
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
- **买不起的格子不再禁用**,改成变灰但仍然可点 —— 点了会告诉你还差多少,
|
|
489
|
+
比「按下去毫无反应」好。
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## [0.14.2] — 2026-09-30
|
|
494
|
+
|
|
495
|
+
### Fixed
|
|
496
|
+
- **调试改过的年龄在面板上看不出来,所以会被当成「猪长太快」。** 实测有一只猪
|
|
497
|
+
`bornAt` 是 5.01 天前、stage 是中年 —— 正好等于调试页「中年」按钮的
|
|
498
|
+
`ageDays: 5`,但面板上没有任何迹象说明这是按出来的。
|
|
499
|
+
|
|
500
|
+
现在:
|
|
501
|
+
|
|
502
|
+
| | |
|
|
503
|
+
|---|---|
|
|
504
|
+
| `applyDevPatch` 设了 `ageDays` | 记 `ageForced = true` |
|
|
505
|
+
| 正常出生 / 开盒 / 重置 | 清掉这个标记 |
|
|
506
|
+
| HUD 和状态页的年龄 | 带一个 🔧 |
|
|
507
|
+
| 调试页顶部 | 明确写「年龄是调试改的」 |
|
|
508
|
+
|
|
509
|
+
**自动长大本身是真实的**:`bornAt` 只有 `layEgg` / `hatch` / `hatchEgg`
|
|
510
|
+
写当前时间、`migrate` 保留原值、以及调试的 `ageDays` —— 没有别的地方会动它。
|
|
511
|
+
阈值也是真实天数:小猪 0 · 青年 1 · 中年 3 · 老年 7。
|
|
512
|
+
|
|
513
|
+
- 新增 **`ageFromNow`**(调试页「⏪ 年龄归零」):把 `bornAt` 拨回现在,
|
|
514
|
+
从此重新按真实时间计算。
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## [0.14.1] — 2026-09-30
|
|
519
|
+
|
|
520
|
+
### Fixed
|
|
521
|
+
- **纸盒点不动,点了只会说「好舒服…」。** 判断条件写错了:
|
|
522
|
+
|
|
523
|
+
```js
|
|
524
|
+
if (view.pig === null) { pokeBox(); return } // ✗ 只判断「完全没有猪」
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
但 `reset` / `adopt` 写出来的存档是 **`hatched: false` 但存档存在** ——
|
|
528
|
+
这时候 `view.pig` 是个真实对象(stage 是 box),不是 null,
|
|
529
|
+
于是点击落到了「摸摸」上,猪回答「好舒服…」。
|
|
530
|
+
|
|
531
|
+
根因是**「有没有猪」和「拆没拆盒」被当成了同一件事**:
|
|
532
|
+
|
|
533
|
+
| 位置 | 之前 | 现在 |
|
|
534
|
+
|---|---|---|
|
|
535
|
+
| 快照的 `hatched` | 硬编码 `true`(只要有存档) | **`state.hatched === true`** |
|
|
536
|
+
| 客户端 normalize | `pig !== null` | `d.hatched === true`(旧宿主缺字段时回退到旧行为) |
|
|
537
|
+
| 戳盒子的判断 | `view.pig === null` | **`view.hatched !== true`** |
|
|
538
|
+
| 渲染纸盒的判断 | `view.pig === null` | **`view.hatched !== true`** |
|
|
539
|
+
|
|
540
|
+
- **「拆开纸盒」按钮同样没反应。** `store.hatch()` 里写着
|
|
541
|
+
`if (state !== null) return false` —— 存档存在就直接拒绝,
|
|
542
|
+
于是 `reset` / `adopt` 出来的盒子**用按钮也打不开**。
|
|
543
|
+
|
|
544
|
+
改成:只有**已经拆开的**才拒绝,并新增 `core.hatch()` **原地开盒** ——
|
|
545
|
+
保留金币、背包、课时这些存档里已有的东西(`hatchEgg` 是造一只全新的猪)。
|
|
546
|
+
|
|
547
|
+
### Added
|
|
548
|
+
- 回归测试:**有存档但没拆的盒子,必须能戳开**,且点击**不能**被当成摸摸。
|
|
549
|
+
验证过它有效(把判断改回 `pig === null` → 那条立刻失败)。
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## [0.14.0] — 2026-09-30
|
|
554
|
+
|
|
555
|
+
### Added
|
|
556
|
+
- **开发者模式。** 按 **Ctrl+Shift+D** 开关(也可以 `window.dshPigDev.toggle()`),
|
|
557
|
+
开了之后图标栏多一个 **🔧 调试** 页,点几下就能把猪掰成任何状态 ——
|
|
558
|
+
开发时不用再等好几天才看得到「老猪」「肺炎」「墓碑」长什么样。
|
|
559
|
+
|
|
560
|
+
| 分组 | 能做什么 |
|
|
561
|
+
|---|---|
|
|
562
|
+
| 状态 | 😊满状态 · 🍎饿 · 🫧脏 · 🥺孤单 · 💤困 |
|
|
563
|
+
| 生病 | 感冒一期 · ☠️肺炎 · 🫁肺结核 · 🤢胃癌 · 💚治好 |
|
|
564
|
+
| 年龄 | 📦纸盒 · 小猪 · 青年 · 中年 · 老年 · 🪦老死 |
|
|
565
|
+
| 资源 | 🪙+100 · 🪙9999 · 🧠+5✨+5💪+5 · 🎒全套药 |
|
|
566
|
+
| 生死 | 💀弄死 · ✨复活 · 📦领养 · 🔄重置 |
|
|
567
|
+
| 面板 | 展开/收起 · ⏩+1小时 · ⏩+1天 |
|
|
568
|
+
|
|
569
|
+
开关状态存在 `localStorage`,刷新还记得。
|
|
570
|
+
|
|
571
|
+
- **`reset` 动作。** 之前只有 `adopt`,而它只对**死猪**有效 ——
|
|
572
|
+
也就是说猪活着的时候没有任何办法重开,只能手动删存档文件。
|
|
573
|
+
更糟的是**运行中的 dsh 把状态缓存在内存里**,所以直接改文件也会被回写覆盖。
|
|
574
|
+
|
|
575
|
+
- `applyDevPatch()` 全程走和游戏一样的边界检查(`clamp100`、`sanitizeTraits`、
|
|
576
|
+
`sanitizeIllness`、`sanitizeInventory`),所以开发者模式**只能造出合法的猪,
|
|
577
|
+
造不出坏掉的存档**。实测:`satiety: 999 → 100`、`cleanliness: -50 → 0`、
|
|
578
|
+
`coins: -5 → 0`、`health: 99 → 5`。
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## [0.13.0] — 2026-09-30
|
|
583
|
+
|
|
584
|
+
### Added
|
|
585
|
+
- **新猪要戳三下才出来。** 领养之后是一个纸盒,戳一下它动一下,戳到第三下才「哇——!」
|
|
586
|
+
蹦出小猪。每一下都有反馈:
|
|
587
|
+
|
|
588
|
+
| 戳第几下 | 反馈 |
|
|
589
|
+
|---|---|---|
|
|
590
|
+
| 1 | 盒子抖一下 ·「里面好像有东西…」 |
|
|
591
|
+
| 2 | 抖得更凶 ·「动了!再戳一下!」 |
|
|
592
|
+
| 3 | 星星粒子 + 「哇——!」→ 小猪蹦出来 |
|
|
593
|
+
|
|
594
|
+
- **纸盒看起来能点。** 之前它就是个静静躺着的 📦,没有任可点的迹象。现在:
|
|
595
|
+
- `dp-box-breathe` —— 2.4 秒一次的呼吸缩放,像里面真有东西在动
|
|
596
|
+
- 底下挂一个「👆 戳三下」的小胶囊提示(`dp-hint-bob` 上下浮动)
|
|
597
|
+
- 光标变成 `pointer`
|
|
598
|
+
|
|
599
|
+
### Fixed
|
|
600
|
+
- **纸盒尺寸客户端写死成 52px,数据里却是 58px。** 现在快照多带一个
|
|
601
|
+
`boxStage`(key/label/emoji/size),客户端照着用 —— 两边再也不会各说各话。
|
|
602
|
+
|
|
603
|
+
- 戳盒子的计数标记原先设在 `.dp-scene` 上,而 CSS 选择器找的是
|
|
604
|
+
`[data-dsh-pig][data-poke]`,动画根本不会触发。**这个 bug 是新加的那条
|
|
605
|
+
「从源码自动推导 hidden 元素」测试配套的严格断言抓出来的** ——
|
|
606
|
+
和 0.8.1 修掉的是同一类:写在 A 上、找的是 B。
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## [0.12.0] — 2026-09-30
|
|
611
|
+
|
|
612
|
+
### Added
|
|
613
|
+
- **学习和打工联动起来了。** 以前三维只是面板上的数字,上课和赚钱是两件不相干的事。
|
|
614
|
+
现在每份工作都吃一个主属性,而**每上完一节课就给对应属性 +1**:
|
|
615
|
+
|
|
616
|
+
| 工作 | 主属性 | 哪些课涨它 |
|
|
617
|
+
|---|---|---|
|
|
618
|
+
| 🧹 打零工 | ✨ 魅力 | 美术 · 音乐 · 礼仪 |
|
|
619
|
+
| 🧱 搬砖 | 💪 武力 | 体育 · 武术 · 劳动 |
|
|
620
|
+
| 💼 上班 | 🧠 智力 | 语文 · 数学 · 政治 |
|
|
621
|
+
|
|
622
|
+
每 1 点属性:**报酬 +6.7%**、**用时 −4%**(最多省一半)。
|
|
623
|
+
报酬封顶 **3 倍**,不然后期没有形状了。
|
|
624
|
+
|
|
625
|
+
实测(上班):
|
|
626
|
+
|
|
627
|
+
| 智力 | 用时 | 报酬 |
|
|
628
|
+
|---|---|---|
|
|
629
|
+
| 0 | 240 分钟 | 900 🪙 |
|
|
630
|
+
| 5 | 192 分钟 | 1200 🪙 |
|
|
631
|
+
| 10 | 144 分钟 | 1500 🪙 |
|
|
632
|
+
| 15 | 120 分钟 | 1800 🪙 |
|
|
633
|
+
|
|
634
|
+
**所以上学不再只是「加个数字」,而是直接把猪的时薪翻上去。**
|
|
635
|
+
|
|
636
|
+
- 打工页把联动写出来了,不用猜:
|
|
637
|
+
|
|
638
|
+
```
|
|
639
|
+
💼 上班
|
|
640
|
+
144 分钟 · 赚 1500 🪙 · 省 40% 时间
|
|
641
|
+
🧠智力 10 · 报酬 +67%
|
|
642
|
+
🧹 打零工
|
|
643
|
+
15 分钟 · 赚 30 🪙
|
|
644
|
+
✨魅力 0 · 去上课就能涨
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### Fixed
|
|
648
|
+
- **猪死了却找不到「领养新猪」按钮。** 按钮被关在 `if (view.pig.soul)` 里面,
|
|
649
|
+
而灵魂要**死后一天**才出现 —— 也就是说猪刚死的时候,墓碑是个纯粹的
|
|
650
|
+
死胡同:既不能复活(没钱买还魂丹时),也不能重开。
|
|
651
|
+
|
|
652
|
+
现在**死亡当刻就能领养**,灵魂只是墓碑上的一个视觉效果。
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## [0.11.1] — 2026-09-30
|
|
657
|
+
|
|
658
|
+
### Fixed
|
|
659
|
+
- **墓碑上写着「今天刚出生」。** `formatAge()` 只判断了 `days < 1`,没判断死亡 ——
|
|
660
|
+
一只出生当天就死了的猪,墓碑上显示的是「今天刚出生」。现在死亡时改成报
|
|
661
|
+
**活了多久**,而且时钟停在死亡那一刻:
|
|
662
|
+
|
|
663
|
+
| 情况 | 之前 | 现在 |
|
|
664
|
+
|---|---|---|
|
|
665
|
+
| 出生 18 小时后病死 | 今天刚出生 | **活了 18 小时** |
|
|
666
|
+
| 活了 3 天 | 今天刚出生 | **活了 3 天** |
|
|
667
|
+
| 活着的猪 | 今天刚出生 | 今天刚出生(不变) |
|
|
668
|
+
|
|
669
|
+
- **每期病期时长改成「越重越久」。** 0.11.0 把每期都设成一天,但现实里
|
|
670
|
+
感冒来得快、肺炎拖得久。现在按病期给不同时长:
|
|
671
|
+
|
|
672
|
+
| 病期 | 时长 |
|
|
673
|
+
|---|---|
|
|
674
|
+
| 感冒 | 1 天 |
|
|
675
|
+
| 发烧 | 1.5 天 |
|
|
676
|
+
| 重感冒 | 2 天 |
|
|
677
|
+
| 肺炎 | 3 天 |
|
|
678
|
+
| **不吃药合计** | **7.5 天** |
|
|
679
|
+
|
|
680
|
+
实测时间线:第 1 天转发烧 → 第 2.5 天转重感冒 → 第 4.5 天转肺炎 → 第 7.5 天死。
|
|
681
|
+
|
|
682
|
+
(0.11.0 之前的旧代码是每期 25 分钟,四期一共 100 分钟 —— 这就是上一只猪
|
|
683
|
+
从感冒到死只用了 102 分钟的原因。)
|
|
684
|
+
|
|
685
|
+
- 阶段推进时**把超出的时间带到下一期**,不再丢弃。跨期的长间隔不会少算。
|
|
686
|
+
|
|
687
|
+
### Changed
|
|
688
|
+
- 测试里的 `advance()` 单位是分钟,之前有人(我)按毫秒传参,导致一次跳了
|
|
689
|
+
8600 万分钟、猪直接老死。补了 `stageMinutes()` 换算,避免再犯。
|
|
690
|
+
|
|
691
|
+
---
|
|
692
|
+
|
|
693
|
+
## [0.11.0] — 2026-09-30
|
|
694
|
+
|
|
695
|
+
### Changed
|
|
696
|
+
- **生病改成以「天」为单位。** 原来每期只有 25 分钟,四期一共 100 分钟 ——
|
|
697
|
+
一顿饭的功夫猪就没了,健康掉得太快。现在**每期一天,四期共四天**,
|
|
698
|
+
够你发现问题、反应、去买药。
|
|
699
|
+
|
|
700
|
+
- **生病的猪赚钱少一半**(`SICK_PAY_MULTIPLIER = 0.5`)。带病打工仍然是
|
|
701
|
+
「穷 + 病」的出路(不会变成新的死锁),但有了代价:
|
|
702
|
+
|
|
703
|
+
| | 搬砖 1 小时 |
|
|
704
|
+
|---|---|
|
|
705
|
+
| 健康 | 160 🪙 |
|
|
706
|
+
| 生病 | **80 🪙** |
|
|
707
|
+
|
|
708
|
+
- **外出会让病情推进得更快**(`SICK_AWAY_MULTIPLIER = 2`)——
|
|
709
|
+
在外面一天等于病情的一天半…实际是**外面半天 = 病情一天**。
|
|
710
|
+
躺着养是最省的选择:
|
|
711
|
+
|
|
712
|
+
| 同样过 12 小时 | 病情 |
|
|
713
|
+
|---|---|
|
|
714
|
+
| 在家躺着 | 还是第 1 期 |
|
|
715
|
+
| 出去上班 | 已经第 2 期 |
|
|
716
|
+
|
|
717
|
+
实现上:病情不再看墙上时钟,而是累计「有效时长」——
|
|
718
|
+
在家 1×、在外 `SICK_AWAY_MULTIPLIER`×。
|
|
719
|
+
|
|
720
|
+
### Added
|
|
721
|
+
- **感冒不管也有小概率自己好**(`SELF_HEAL_CHANCE`,按病期给概率):
|
|
722
|
+
|
|
723
|
+
| 病期 | 自愈概率 |
|
|
724
|
+
|---|---|
|
|
725
|
+
| 第 1 期 | 25% |
|
|
726
|
+
| 第 2 期 | 12% |
|
|
727
|
+
| 第 3 期 | 5% |
|
|
728
|
+
| 第 4 期 | **0%** —— 到这一步不吃药就是死 |
|
|
729
|
+
|
|
730
|
+
自愈时会恢复 1 点健康,并播报「自己好了 💚」。
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
## [0.10.0] — 2026-09-30
|
|
735
|
+
|
|
736
|
+
### Fixed
|
|
737
|
+
- **生病会把自己饿死 —— 这是个死锁。** 原来 `awayBlockedReason()` 里写着
|
|
738
|
+
`if (state.illness !== null) return 'sick'`,于是:
|
|
739
|
+
|
|
740
|
+
```
|
|
741
|
+
生病 → 不能打工 → 没金币 → 买不起药 → 病好不了 → 只能等死
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
现在**生病的猪照样能出门打工/上学/旅行**,只有健康掉到 **1(疾病最后一期,
|
|
745
|
+
再下一期就是死)** 才真的出不了门(新的拒绝原因 `weak`)。
|
|
746
|
+
猪既然还站得起来,就该能自己挣药钱。
|
|
747
|
+
|
|
748
|
+
实测:感冒 · 3 金币 → 打一次零工 +30 🪙 → 够买 12 🪙 的普通药。
|
|
749
|
+
|
|
750
|
+
- **界面把出路说清楚。** 生病横幅在「买不起药」时会多一行:
|
|
751
|
+
「钱不够也没关系 —— 生病照样能出门打工,先赚 12 🪙 买「普通药」」。
|
|
752
|
+
买得起时不显示。
|
|
753
|
+
|
|
754
|
+
### Changed
|
|
755
|
+
- **初始金币 60 → 500。** 60 块钱买完最便宜的药就没了,而生病又不能打工,
|
|
756
|
+
开局很容易卡死。500 够买任何一期的药,也够交学费。
|
|
757
|
+
|
|
758
|
+
老存档会**一次性补到 500**(`STATE_VERSION` 4 → 5,按版本号判断,只补一次)。
|
|
759
|
+
损坏数据(负数金币)不补,只归零。
|
|
760
|
+
|
|
761
|
+
### Added
|
|
762
|
+
- `awayBlockedReason()` 新增 `weak`;客户端多一条对应文案「太虚弱了,先养好再出门」。
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
## [0.9.3] — 2026-09-30
|
|
767
|
+
|
|
768
|
+
### Fixed
|
|
769
|
+
- **补上 0.9.2 没修完的那一半:插件自己的运行时标识符。** 0.9.2 修好了
|
|
770
|
+
`cordis.patch.yml` 里的 `name`,但客户端模块还是按旧 id 注册的:
|
|
771
|
+
|
|
772
|
+
| 位置 | 之前 | 现在 |
|
|
773
|
+
|---|---|---|
|
|
774
|
+
| `client.js` 的 `__ModuleLoader__.load({ id })` | `dsh-pig` | `dsh-piggy` |
|
|
775
|
+
| `client.js` 的 `exports.name` | `dsh-pig` | `dsh-piggy` |
|
|
776
|
+
| `index.js` 的 `export const name` | `dsh-pig` | `dsh-piggy` |
|
|
777
|
+
|
|
778
|
+
客户端的 bundle 清单是按 id 收的,id 和包名对不上,这个插件的 client 就不会被列进去,
|
|
779
|
+
组件永远不挂载。(感谢 pi 定位。)
|
|
780
|
+
|
|
781
|
+
- **这些没改,也不该改**:
|
|
782
|
+
|
|
783
|
+
| | 为什么 |
|
|
784
|
+
|---|---|
|
|
785
|
+
| HTTP 路由 `/dsh-pig/state`、`/act`、`/art` | 内部契约,改了没有好处 |
|
|
786
|
+
| 存档目录 `$DSH_HOME/dsh-pig/state.json` | **改了会丢正在养的那只猪** |
|
|
787
|
+
| CSS 选择器 `[data-dsh-pig]`、`localStorage` 的 `dsh-pig:open` / `:position` | 内部标识;改了会丢掉用户保存的面板位置 |
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## [0.9.2] — 2026-09-30
|
|
792
|
+
|
|
793
|
+
### Fixed
|
|
794
|
+
- **改名后猪整个消失了。** 包从 `dsh-pig` 改名成 `dsh-piggy` 时,漏改了插件自带的
|
|
795
|
+
`cordis.patch.yml`:
|
|
796
|
+
|
|
797
|
+
```yaml
|
|
798
|
+
- insert:
|
|
799
|
+
- id: dsh-pig
|
|
800
|
+
name: dsh-pig # ← 包已经不叫这个名字了
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
宿主那一半**看起来是好的** —— 路由 `/dsh-pig/state` 照常 200,快照也正常,
|
|
804
|
+
因为加载器靠 `node_modules` 里残留的旧符号链接仍然解析得到这个目录。
|
|
805
|
+
但**客户端那一半被静默丢掉了**:注册时按 `dsh-pig` 去读 `package.json`,
|
|
806
|
+
读出来的 `name` 是 `dsh-piggy`,对不上,于是这个插件的 client 根本没有进入
|
|
807
|
+
客户端的 bundle 清单 —— 组件永远不挂载,屏幕上就是没有猪。
|
|
808
|
+
|
|
809
|
+
验证方式是把 `/plugins/??...` 那两个实际发出的 bundle 请求抓下来,
|
|
810
|
+
清单里列了 `modlens` / `dshmarket` / `dsh-context` / `dsh-better-sidebar`,
|
|
811
|
+
**唯独没有 `dsh-pig`**。
|
|
812
|
+
|
|
813
|
+
修:`name: dsh-piggy`,并清掉 `node_modules/dsh-pig` 那个残留链接。
|
|
814
|
+
|
|
815
|
+
### Added
|
|
816
|
+
- 一条回归测试:**`cordis.patch.yml` 里的 `name` 必须和 `package.json` 的 `name` 完全一致**。
|
|
817
|
+
已验证它有效(把名字改回 `dsh-pig` → 那条立刻失败)。
|
|
818
|
+
这和 0.8.1 修掉的「写死类名的测试」是同一类问题:**静默失效的引用**。
|
|
819
|
+
|
|
820
|
+
---
|
|
821
|
+
|
|
822
|
+
## [0.9.1] — 2026-09-29
|
|
823
|
+
|
|
824
|
+
### Fixed
|
|
825
|
+
- **测试里的 `readCss()` 一直在读一份残缺的样式表。** 它只认「行首就是引号」的
|
|
826
|
+
字面量,而 CSS 数组里有跨行用 `+` 拼接的条目 —— 「摸摸的手」那个 data URI
|
|
827
|
+
就横跨七行。于是从它开始,后面所有规则在测试眼里都消失了:
|
|
828
|
+
|
|
829
|
+
```
|
|
830
|
+
实测:拼出来的 CSS 花括号差 1 个(被截断的 url( 吞掉了后面的规则)
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
浏览器拿到的是正确拼接的字符串,所以线上一直是好的 —— **但这个测试工具本身的
|
|
834
|
+
缺陷意味着它对后半张表的断言全是假的**。现在同时接受行首和 `+` 续行两种字面量。
|
|
835
|
+
- 新增一条自检:**拼出来的样式表必须花括号配平**,并且光标 data-URI 必须完整
|
|
836
|
+
(以 `</svg>` 结尾)。这类截断今后会直接报错,而不是让后面的断言静默失真。
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
## [0.9.0] — 2026-09-29
|
|
841
|
+
|
|
842
|
+
### Changed
|
|
843
|
+
- **小猪和老年猪换成了照参考图重画的手绘形象。** 之前两版都画错了:
|
|
844
|
+
第一版是「暖棕描边 + 正面 Q 版」,第二版虽然改成了侧面平涂,风格仍然对不上。
|
|
845
|
+
这一版是直接按参考图拆的:
|
|
846
|
+
|
|
847
|
+
| | 参考图 |
|
|
848
|
+
|---|---|
|
|
849
|
+
| 身体 | `#FFD1AF` 蜜桃色,平涂、**零描边** |
|
|
850
|
+
| 耳朵 | `#E95892` 洋红**圆头弧线**(不是填充三角形) |
|
|
851
|
+
| 鼻子 | `#FF8195` **有机形状**、微微倾斜,两个深色鼻孔 |
|
|
852
|
+
| 眼睛 | `#373A32`,刻意画得不规则,不是正圆 |
|
|
853
|
+
| 尾巴 | `#FFD1AF` 圆头线条卷成的圈 |
|
|
854
|
+
| 老年猪 | 同一头猪褪色成 `#F1C09D`,耳朵 `#CF6C89`;眼睛变成**两道弧线**(眯着),
|
|
855
|
+
外加灰眉毛、皱纹、两撇白胡子和一撮白下巴 |
|
|
856
|
+
|
|
857
|
+
两张都缩放进 64×64 的正方形视框(原图内容 301×279 → 60×55.6),
|
|
858
|
+
这样和 emoji 阶段在同一套 `--pig-size` 下尺寸一致。
|
|
859
|
+
|
|
860
|
+
- 体型重新对齐:小猪 40px(手绘)、青年猪 48px、中年猪 62px(都是 🐖)、
|
|
861
|
+
老年猪 56px(手绘)。
|
|
862
|
+
|
|
863
|
+
---
|
|
864
|
+
|
|
865
|
+
## [0.8.2] — 2026-09-29
|
|
866
|
+
|
|
867
|
+
### Changed
|
|
868
|
+
- **六个阶段全部用 🐖,暂时不画图。** 前面手绘的 `assets/piglet.svg`、
|
|
869
|
+
`assets/elder.svg` 虽然结构照抄了 emoji(侧面、无描边、洋红卷耳),
|
|
870
|
+
但风格终究对不上,先撤下来,等拿到参考图再重做。现在靠**体型**区分:
|
|
871
|
+
|
|
872
|
+
| 阶段 | 图标 | 大小 |
|
|
873
|
+
|---|---|---|
|
|
874
|
+
| 纸盒 | 📦 | 58px |
|
|
875
|
+
| 小猪 | 🐖 | 38px |
|
|
876
|
+
| 青年猪 | 🐖 | 48px |
|
|
877
|
+
| 中年猪 | 🐖 | 62px |
|
|
878
|
+
| 老年猪 | 🐖 | 54px · **褪色**(`grayscale(.5)` + 透明度) |
|
|
879
|
+
| 墓碑 | 🪦 | 52px |
|
|
880
|
+
|
|
881
|
+
老年猪没有画图可用了,改用一个 CSS 滤镜让毛色「淡下去」——`[data-faded="true"]`。
|
|
882
|
+
- SVG 文件和 `/dsh-pig/art/` 路由**保留不动**,只是阶段定义里不再有 `art` 字段。
|
|
883
|
+
参考图到位后,只要在 `data.js` 里给对应阶段加回 `art: 'xxx'` 就能接上,
|
|
884
|
+
客户端和路由已经写好而且有测试覆盖。
|
|
885
|
+
|
|
886
|
+
---
|
|
887
|
+
|
|
888
|
+
## [0.8.1] — 2026-09-29
|
|
889
|
+
|
|
890
|
+
### Fixed
|
|
891
|
+
- **猪闲着的时候身边也挂着 💼 和进度条。** `.dp-work{display:flex}` 的优先级
|
|
892
|
+
(`[data-dsh-pig] .dp-work` = 0,2,0)压过 UA 表的 `[hidden]{display:none}`(0,1,0),
|
|
893
|
+
所以 `work.hidden = true` 只是个摆设 —— 元素照画不误。补上
|
|
894
|
+
`[data-dsh-pig] .dp-work[hidden]{display:none}`,顺手把同样会踩坑的
|
|
895
|
+
`.dp-soul` / `.dp-pig-img` / `.dp-pig-emoji` 一起补进那条规则。
|
|
896
|
+
- **而且守护这条规则的测试本身是坏的。** 它把类名写死成
|
|
897
|
+
`['dp-card','dp-bar','dp-content','dp-hud','dp-bubble']`,我后来加
|
|
898
|
+
`.dp-work` 等元素时没同步这个数组,所以**测试一直是绿的**。
|
|
899
|
+
现在改成从源码里自动推导:扫出所有 `X.hidden =` 的赋值,再把变量映射回
|
|
900
|
+
它创建的 class,逐个断言存在 `[hidden]` 规则。以后再加会隐藏的元素,
|
|
901
|
+
不补 CSS 就会立刻报红。
|
|
902
|
+
|
|
903
|
+
(验证过这条测试真的有效:把 `.dp-work[hidden]` 删掉 → 正好那一条失败;
|
|
904
|
+
加回来 → 全绿。)
|
|
905
|
+
|
|
906
|
+
---
|
|
907
|
+
|
|
908
|
+
## [0.8.0] — 2026-09-29
|
|
909
|
+
|
|
910
|
+
### Changed
|
|
911
|
+
- **等级换成了年龄。** 猪不再是一条要刷的经验条,而是一段**用天数计的生命**:
|
|
912
|
+
|
|
913
|
+
| 阶段 | 图标 | 大小 | 何时 |
|
|
914
|
+
|---|---|---|---|
|
|
915
|
+
| 纸盒 | 📦 | 54px | 一开始 |
|
|
916
|
+
| 小猪 | 🐖 手绘 | 40px | 拆开纸盒,蹦出来 |
|
|
917
|
+
| 青年猪 | 🐖 | 50px | 第 1 天 |
|
|
918
|
+
| 中年猪 | 🐖 | 62px | 第 3 天 |
|
|
919
|
+
| 老年猪 | 🐖 手绘 | 56px | 第 7 天 |
|
|
920
|
+
| 墓碑 | 🪦 | 54px | 第 14 天自然老去,或病死 |
|
|
921
|
+
| 墓碑 + 灵魂 👻 | | | 死后 1 天仍未复活/领养 |
|
|
922
|
+
|
|
923
|
+
**年龄按真实天数走**,所以关掉 DSH 期间猪照样在长大。所有阶段都用同一个 🐖
|
|
924
|
+
形象,靠**体型**区分成长 —— 小猪和老年猪另外有手绘的形象。
|
|
925
|
+
- **XP 不再决定形态,改喂体重。** 「吃你的真实工作长大」还在,但长的是分量,
|
|
926
|
+
不是等级。`经验` 那一行在面板里换成了 `🎂 年龄`。
|
|
927
|
+
- **死亡有了后续。** 墓碑立起来之后有两条路:**还魂丹**把它叫回来
|
|
928
|
+
(金币、收藏、上过的课都保留),或者**领养新猪**(保留回忆,重新从纸盒开始)。
|
|
929
|
+
两条都不选,一天之后墓碑上会多一个 👻。
|
|
930
|
+
- 原来的 7 级阶梯(猪蛋 → 野猪王)整体删除。存档里的 `xp` 原样保留,
|
|
931
|
+
你的猪按 `bornAt` 的真实年龄重新定位到对应阶段。
|
|
932
|
+
|
|
933
|
+
### Added
|
|
934
|
+
- `assets/piglet.svg` 和 `assets/elder.svg` —— 小猪和老年猪的手绘形象。
|
|
935
|
+
由插件自己的 `/dsh-pig/art/<name>.svg` 路由伺服:**图片是仓库里真实的 .svg 文件**,
|
|
936
|
+
不是塞进客户端包里的一坨字符串。
|
|
937
|
+
- `/dsh-pig/art/` 路由对文件名做了白名单式校验(`^[a-z][a-z0-9-]{0,31}\.svg$`),
|
|
938
|
+
请求里的任何东西都不可能走出 `./assets`。
|
|
939
|
+
- `tools/` 之外新增的可见行为:`拍一拍` 的空状态文案改成「门口放着一个纸盒,里面窸窸窣窣 📦」,
|
|
940
|
+
按钮从「孵一只」改成「拆开纸盒」。
|
|
941
|
+
|
|
942
|
+
---
|
|
943
|
+
|
|
944
|
+
## [0.7.1] — 2026-09-29
|
|
945
|
+
|
|
946
|
+
### Fixed
|
|
947
|
+
- **升级快得离谱。** 实际用量摆出来就很清楚 —— 4.6 小时里:
|
|
948
|
+
|
|
949
|
+
```
|
|
950
|
+
tools 744 次 × 3 = 2232 xp ← 94% 的 XP 全在这里
|
|
951
|
+
turns 17 次 × 5 = 85
|
|
952
|
+
messages 21 次 × 2 = 42
|
|
953
|
+
活动计数:打工 0 · 上课 0 · 旅行 0
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
一个下午光靠工具调用就从蛋喂到了「猪皇」,**而游戏内容一次都没用上**。
|
|
957
|
+
两个原因叠加:单次工具调用给 3 点太肥,等级表又太浅。
|
|
958
|
+
|
|
959
|
+
| | 之前 | 现在 |
|
|
960
|
+
|---|---|---|
|
|
961
|
+
| 工具调用 / 回合 / 消息 | 3 / 5 / 2 | **1 / 2 / 1** |
|
|
962
|
+
| 被动 XP 每小时(实测用量) | 513 | **174** |
|
|
963
|
+
| 猪皇 (Lv5) | 1200 xp | **2200** |
|
|
964
|
+
| 野猪王 (Lv7) | 8000 xp | **15000** |
|
|
965
|
+
| **从蛋到野猪王** | **15.6 小时** | **86 小时**(约 3 周日常使用) |
|
|
966
|
+
|
|
967
|
+
- **活动 XP 同步上调,让「玩」成为快车道。** 之前一次 4 小时「上班」只给 320 xp,
|
|
968
|
+
还不到同样 4 小时挂机的零头 —— 派猪出门反而亏。现在:
|
|
969
|
+
|
|
970
|
+
| 活动 | 之前 | 现在 | 相当于多少小时被动 |
|
|
971
|
+
|---|---|---|---|
|
|
972
|
+
| 打零工 15 分钟 | 12 | 40 | 0.2 |
|
|
973
|
+
| 搬砖 1 小时 | 60 | 200 | 1.2 |
|
|
974
|
+
| 上班 4 小时 | 320 | **900** | 5.2 |
|
|
975
|
+
| 小学 30 分钟 | 20 | 60 | 0.3 |
|
|
976
|
+
| 大学 2 小时 | 95 | 320 | 1.8 |
|
|
977
|
+
| 研究生 6 小时 | 340 | **1100** | 6.3 |
|
|
978
|
+
| 郊游 1 小时 | 22 | 80 | 0.5 |
|
|
979
|
+
| 名山大川 3 小时 | 75 | 260 | 1.5 |
|
|
980
|
+
| 看海 8 小时 | 210 | 700 | 4.0 |
|
|
981
|
+
| 出国 1 天 | 620 | **2000** | 11.5 |
|
|
982
|
+
|
|
983
|
+
已有的存档不受影响:xp 数值原样保留,2443 在两张表里都落在「猪皇」。
|
|
984
|
+
|
|
985
|
+
---
|
|
986
|
+
|
|
987
|
+
## [0.7.0] — 2026-09-29
|
|
988
|
+
|
|
989
|
+
### Added
|
|
990
|
+
- **外出时有动作了。** 之前猪出去打工/上学/旅行就只是原地站着,现在场景里会多出
|
|
991
|
+
它正在用的东西,猪也有各自的姿势:
|
|
992
|
+
|
|
993
|
+
| 活动 | 猪的动画 | 场景里的道具 |
|
|
994
|
+
|---|---|---|
|
|
995
|
+
| 💼 打工 | `dp-typing` 打字的那种小幅抖动 | 工作 emoji(💻 上班 / 🧹 打零工 / 🧱 搬砖) |
|
|
996
|
+
| 📚 学习 | `dp-reading` 慢速歪头,像在看书 | 科目的 emoji(📖 语文 / 🔢 数学 …) |
|
|
997
|
+
| 🧳 旅行 | `dp-walking` 走路的弹跳 | 目的地的 emoji(🌊 看海 / 🏔 名山 …) |
|
|
998
|
+
|
|
999
|
+
道具和进度条都放在**猪的左边**并且场景向左扩,所以**猪自己一个像素都不动**。
|
|
1000
|
+
进度条按快照里的 `activity.progress` 走。
|
|
1001
|
+
|
|
1002
|
+
### Fixed
|
|
1003
|
+
- **吃饭不再让猪变脏。** `careEffects()` 里写的是
|
|
1004
|
+
`cleanliness: item.cleanliness ?? spec.cleanliness` —— 苹果没有声明 `cleanliness`,
|
|
1005
|
+
于是**回退到了「喂食」这个动作的基线 -6**。吃个苹果掉 6 点清洁,就是这么来的。
|
|
1006
|
+
现在喂食的基线是 0,只有真正会弄脏的食物(奶油蛋糕 −8、大碗拉面 −6、肉骨头 −4)
|
|
1007
|
+
才扣,而且幅度减半。
|
|
1008
|
+
- **数值整体重新平衡。** 活动时长从分钟改成小时后,原来的数值是**双重扣减**:
|
|
1009
|
+
既按 1.8× 的「在外消耗」走衰减,又扣一次为分钟时代写好的固定消耗
|
|
1010
|
+
(「上班」原写着 饱食 −78、清洁 −90)。现在:
|
|
1011
|
+
|
|
1012
|
+
| | 之前 | 现在 |
|
|
1013
|
+
|---|---|---|
|
|
1014
|
+
| 饱食/心情/清洁衰减 | 0.14 / 0.09 / 0.11 每分钟 | **0.08 / 0.06 / 0.07** |
|
|
1015
|
+
| 在外倍数 | 1.8× | **1.4×** |
|
|
1016
|
+
| 上班 4 小时净消耗 | 饱食 −138 · 清洁 −137(直接归零) | **饱食 −61 · 清洁 −50** |
|
|
1017
|
+
| 出国 1 天 | 三项全 0 **且生病** | **15 / 15 / 15,不生病** |
|
|
1018
|
+
|
|
1019
|
+
还有一条规则:**活动的消耗不能让任何一条归零**(下限 15)——
|
|
1020
|
+
猪从一日游回来应该是「饿惨了」,等着你喂它,而不是你还没反应过来它就躺平了。
|
|
1021
|
+
- **在外不会生病。** 原来 `decay()` 先结算活动(`activity` 变 null)再做疾病判定,
|
|
1022
|
+
所以「在外不生病」的判断根本没生效 —— 出去玩一天回来必定生病。
|
|
1023
|
+
现在先捕获 away 标记再结算。
|
|
1024
|
+
- 挂机 12 小时:饱食 42 · 清洁 50 · 心情 57,**不生病**。
|
|
1025
|
+
|
|
1026
|
+
---
|
|
1027
|
+
|
|
1028
|
+
## [0.6.1] — 2026-09-29
|
|
1029
|
+
|
|
1030
|
+
### Added
|
|
1031
|
+
- **商店从 12 件扩到 21 件**,并按货架分组(🍎食物 6 · 🧼洗浴 5 · 🪀玩具 5 · 💊药品 4 · ✨复活 1)。
|
|
1032
|
+
平铺 21 件会变成一条长龙,所以每一档加了小标题。
|
|
1033
|
+
- **缺货时猪会自己说话**,不再是一句含糊的「这个操作没成」:
|
|
1034
|
+
|
|
1035
|
+
| 情况 | 猪说 |
|
|
1036
|
+
|---|---|
|
|
1037
|
+
| 没有食物 | 「没有吃的啦,快去买一点 🍎」 |
|
|
1038
|
+
| 没有洗浴用品 | 「没有洗浴用品了,去买点吧 🧼」 |
|
|
1039
|
+
| 没有玩具 | 「没有玩具了,去商店看看 🪀」 |
|
|
1040
|
+
|
|
1041
|
+
### Changed
|
|
1042
|
+
- **说话气泡浮在猪的头顶正上方**,尾巴朝下指着猪。之前为了躲开心形我把气泡放到了
|
|
1043
|
+
猪的左侧 —— 那个取舍做反了:**该让心形避让气泡,不是把气泡赶到一边去**。
|
|
1044
|
+
现在心形 `z-index:1` 从后面升起、气泡 `z-index:2` 在上面;
|
|
1045
|
+
气泡靠右边缘对齐,再长的台词也不顶出窗口。
|
|
1046
|
+
|
|
1047
|
+
---
|
|
1048
|
+
|
|
1049
|
+
## [0.6.0] — 2026-09-29
|
|
1050
|
+
|
|
1051
|
+
### Changed
|
|
1052
|
+
- **喂食 / 洗澡 / 玩耍都要花道具了**,照 QQ 宠物原版的设计。它的 `StoreInventory`
|
|
1053
|
+
把背包分成 **`food` / `commodity` / `medicine` / `background`** 四类,
|
|
1054
|
+
而它自己的治病流程就是「在背包找对应的药 → 用掉 → 恢复健康」——
|
|
1055
|
+
喂食、洗澡、玩耍是同一套逻辑。现在:
|
|
1056
|
+
- 点「喂食 / 洗澡 / 玩耍」**弹出背包**,告诉你有什么、还剩几个、每样加多少
|
|
1057
|
+
- 用了就消耗一个;点「算了」不消耗
|
|
1058
|
+
- **自带一个免费小皮球**,所以玩具一件都没有时「玩耍」照样能用(且永不消耗)
|
|
1059
|
+
- 没有任何食物/洗浴用品时,动作会被明确拒绝(`no-item`),不是静默失败
|
|
1060
|
+
- **商店按货架重组**:🍎食物(苹果/肉骨头/奶油蛋糕)· 🧼洗浴(香皂/沐浴露/泡泡浴)
|
|
1061
|
+
· 🪀玩具(悠悠球/布偶/旋转木马)· 💊药品四级 · ✨还魂丹。
|
|
1062
|
+
- **工作/学习/旅行改成真正的时间投入**(原版就是按小时计的):
|
|
1063
|
+
|
|
1064
|
+
| | 时长 | 代价 |
|
|
1065
|
+
|---|---|---|
|
|
1066
|
+
| 🧹 打零工 | 15 分钟 | → 30 🪙 |
|
|
1067
|
+
| 🧱 搬砖 | 1 小时 | → 160 🪙 |
|
|
1068
|
+
| 💼 上班 | 4 小时 | → 900 🪙 |
|
|
1069
|
+
| 📚 小学 | 30 分钟 | 学费 40 🪙 |
|
|
1070
|
+
| 📚 大学 | 2 小时 | 学费 220 🪙 |
|
|
1071
|
+
| 📚 研究生 | 6 小时 | 学费 900 🪙 |
|
|
1072
|
+
| 🏞 郊游 | 1 小时 | 60 🪙 |
|
|
1073
|
+
| 🏔 名山大川 | 3 小时 | 200 🪙 |
|
|
1074
|
+
| 🌊 看海 | 8 小时 | 620 🪙 |
|
|
1075
|
+
| 🌍 出国 | 1 天 | 2000 🪙 |
|
|
1076
|
+
|
|
1077
|
+
- **学校是阶梯,不是菜单。** QQ 宠物所有宠物都从小学起步,所以
|
|
1078
|
+
**大学要先把小学九门课各上一次**(9 节),**研究生要先念完大学九门课**。
|
|
1079
|
+
锁住的学段按钮仍然**可以点**,点进去会告诉你还差多少(`🔒 要先念完小学九门课各上一次(3/9)`),
|
|
1080
|
+
只是里面的课点不了。老存档的课时会算作小学课时,不会被锁在门外。
|
|
1081
|
+
|
|
1082
|
+
### Fixed
|
|
1083
|
+
- **左键猪现在是「摸摸的手」光标**(内联 SVG,不用素材),不再是一个箭头。
|
|
1084
|
+
- **心形飘在猪头顶正上方**:原来用的是场景的固定坐标,场景展开后有面板那么宽,
|
|
1085
|
+
粒子就全飘到猪旁边去了。现在锚定到猪本身。
|
|
1086
|
+
- **收起状态下也能看到说话气泡**:气泡其实一直显示着,但它和猪重叠、
|
|
1087
|
+
而猪在 DOM 里排在后面把气泡盖住了。现在收起时气泡浮在猪的**头顶正上方**,
|
|
1088
|
+
尾巴朝下指着猪(`z-index:2`),心形从后面升起(`z-index:1`)。
|
|
1089
|
+
靠右边缘对齐,所以再长的台词也不会顶出窗口。
|
|
1090
|
+
|
|
1091
|
+
### Added
|
|
1092
|
+
- `careView()` / `studyView()` —— 面板需要的「能用什么道具」「哪一学段解锁了」。
|
|
1093
|
+
- 预览台补上道具货架、学段门槛和长时间活动。
|
|
1094
|
+
|
|
1095
|
+
---
|
|
1096
|
+
|
|
1097
|
+
## [0.5.0] — 2026-09-29
|
|
1098
|
+
|
|
1099
|
+
### Changed
|
|
1100
|
+
- **右键猪才出菜单,左键变成摸摸。** 原来左键切换面板,随手一点就会开关。
|
|
1101
|
+
现在 `contextmenu` 负责开关(`preventDefault` 掉浏览器原生菜单),左键只让猪
|
|
1102
|
+
做个被摸摸的反应。右键不好发现,所以给场景加了原生 tooltip:
|
|
1103
|
+
「左键摸摸 · 右键打开面板 · 拖动可移动」。
|
|
1104
|
+
- **面板不再把猪挤走,也不再超出页面。** 关键改动是让面板**脱离文档流**
|
|
1105
|
+
(`position:absolute`)—— 之前在流内时它会撑大外层容器,而外层一变宽,猪就跟着移。
|
|
1106
|
+
现在外层容器的尺寸完全由猪决定,`fitPanel()` 负责把面板放到:
|
|
1107
|
+
- **空间更大的一侧**:上方不够就翻到猪的下方(猪被拖到窗口顶部时)
|
|
1108
|
+
- **水平方向**:面板比猪宽,靠左停放时会顶出左边,用负 `right` 平移回来
|
|
1109
|
+
- **高度按可用空间算**,每个标签页渲染后重算一次
|
|
1110
|
+
|
|
1111
|
+
实测五个停靠位置(四角 + 正下):**猪移动量全部为 0**,猪 / HUD / 面板全部完整可见。
|
|
1112
|
+
|
|
1113
|
+
### Fixed
|
|
1114
|
+
- **猪能放到对话框旁边了。** 之前有一段 `keepClearOfComposer()`:它会**强制**把猪顶到
|
|
1115
|
+
输入框上方(`host.style.bottom = Math.max(userBottom, floor)`),所以你没法把它停在
|
|
1116
|
+
输入框旁边。那段夹紧是当年为了绕开"猪盖住发送按钮吃掉点击"而加的 ——
|
|
1117
|
+
但 `pointer-events` 已经正确解决了那个问题(只有猪实际绘制的像素接收点击),
|
|
1118
|
+
于是它只剩下副作用。现在只保留"别跑出窗口"这一条。
|
|
1119
|
+
- 猪的水平夹紧要算上场景的左右内边距(`PIG_PADDING_X`),否则它会以 2px 探出屏幕。
|
|
1120
|
+
- **`top` 和 `bottom` 必须显式写 `auto`**:用 `''` 清除会回退到样式表里的那条,
|
|
1121
|
+
两边同时生效,绝对定位的盒子被压成 **4px 高**。
|
|
1122
|
+
- 垂直夹紧始终按**展开时**的场景高度预留,否则猪停得靠上时,一展开面板就会把 HUD 顶出屏幕。
|
|
1123
|
+
- 展开时场景宽度等于面板宽度,HUD 和气泡才有地方待(外层变宽不影响猪,它靠右对齐)。
|
|
1124
|
+
|
|
1125
|
+
### Added
|
|
1126
|
+
- 预览台新增 `pigStub.pet()` / `pigStub.dragBy(dx, dy)`,右键、点击、拖拽都能在
|
|
1127
|
+
真实浏览器里复现。
|
|
1128
|
+
- 假 DOM 补上 `getBoundingClientRect` 和窗口几何 —— 缺了几何时 `clampPig()` 会抛异常,
|
|
1129
|
+
而 `apply()` 把它兜住,表现为"猪根本没挂上"。
|
|
1130
|
+
|
|
1131
|
+
---
|
|
1132
|
+
|
|
1133
|
+
## [0.4.0] — 2026-09-29
|
|
1134
|
+
|
|
1135
|
+
### Changed
|
|
1136
|
+
- **整套视觉换成动森风格**,依据
|
|
1137
|
+
[guokaigdg/animal-island-ui](https://github.com/guokaigdg/animal-island-ui)
|
|
1138
|
+
的 `docs/design-system`(`design-tokens.md` + 独立复刻用的 `css-variables.md`)。
|
|
1139
|
+
设计 token 声明在组件根节点上而**不是 `:root`**:宿主的自定义属性既不该被污染,
|
|
1140
|
+
也不该能覆盖这里。
|
|
1141
|
+
|
|
1142
|
+
| 从 | 到 |
|
|
1143
|
+
|---|---|
|
|
1144
|
+
| 深色导航蓝面板 `rgba(22,26,35,.95)` | **奶油羊皮纸** `#f8f8f0` + 2px 暖棕边框 `#e5dcc6` |
|
|
1145
|
+
| 白色文字 | **暖棕** `#794f27` / `#725d42` / `#9f927d`(规范禁止纯黑与冷灰) |
|
|
1146
|
+
| 15px 圆角 | **20px**(卡片),按钮与输入框一律 **50px 药丸** |
|
|
1147
|
+
| 青色 `#7ED0A0` 属性条 | 动森配色:饱食 `#f7cd67` · 心情 `#f8a6b2` · 清洁 `#82d5bb` · 健康 `#8ac68a`,轨道带内阴影 |
|
|
1148
|
+
| 通用按钮 | **次要按钮** = 奶油药丸 + 2px 边框 + 柔和浮起;**主按钮** = 青色药丸 + `0 3px 0` **游戏 3D 底边** |
|
|
1149
|
+
| 深色高亮 | 侧边栏 token `#b7c6e5` 做选中态、`#d6dff0` 做悬停 |
|
|
1150
|
+
| 系统字体 | **Nunito + Noto Sans SC**(按规范的独立复刻配方从 Google Fonts 加载,`display=swap`,失败则退回系统字体) |
|
|
1151
|
+
|
|
1152
|
+
还照规范的硬规则调整了:卡片**用边框而不是投影**表达层次、悬停 `translateY(-1px)`、
|
|
1153
|
+
按下 `translateY(2px)`、过渡统一 `cubic-bezier(.4,0,.2,1)` 且时长 0.15–0.35s、
|
|
1154
|
+
焦点环用青/黄而非蓝色、所有阴影都用暖色 `rgba(61,52,40,·)` 而不是冷黑。
|
|
1155
|
+
|
|
1156
|
+
### Fixed
|
|
1157
|
+
- **重写 CSS 时弄丢了 `pointer-events:none`**,会让组件的透明区域挡住页面点击
|
|
1158
|
+
—— 这个症状历史上表现为"发消息没反应",而整条链路其实是健康的。
|
|
1159
|
+
**测试当场抓到了它。**
|
|
1160
|
+
- **面板限高补 10px 顶部余量**:内容长的标签页原来紧贴窗口上边缘。
|
|
1161
|
+
|
|
1162
|
+
### Added
|
|
1163
|
+
- **测试里的 `readCss()`**:把 bundle 里拼接出来的样式表重新组装成浏览器实际拿到的
|
|
1164
|
+
字符串再做静态断言。原来直接对源码跑正则,**跨字符串字面量的规则看起来就像不存在**
|
|
1165
|
+
—— 一条正确的 `pointer-events` 规则因此被误判为缺失,而注释里的撇号
|
|
1166
|
+
("the UA sheet**'**s")还会进一步骗过天真的引号扫描。
|
|
1167
|
+
|
|
1168
|
+
---
|
|
1169
|
+
|
|
1170
|
+
## [0.3.2] — 2026-09-29
|
|
1171
|
+
|
|
1172
|
+
### Fixed
|
|
1173
|
+
- **猪不再吞掉“发送消息”的点击。** 宿主把输入框和发送按钮也停在右下角,而猪在
|
|
1174
|
+
`right:18px/bottom:18px`,两者重叠(实测视口 780×493:发送按钮 `x715-749 y421-455`
|
|
1175
|
+
完全落在猪的盒子 `x686-756 y294-351` 的覆盖范围内)且 `z-index:2147483000`、
|
|
1176
|
+
`pointer-events` 默认 —— `document.elementFromPoint(按钮中心)` 返回的是
|
|
1177
|
+
`DIV.dp-pig`,点发送等于点猪:消息从未发到服务器,表面上却像“模型不回复”。
|
|
1178
|
+
- 外层容器改为 `pointer-events:none`,只有猪本体和面板本身(`[data-dsh-pig]>*`)
|
|
1179
|
+
接收点击,容器空白区域不再拦截下层 UI。
|
|
1180
|
+
- 新增 `keepClearOfComposer()`:输入框贴底时把猪抬到输入框上方(`bottom` 取
|
|
1181
|
+
`用户位置` 与 `视口高 − 输入框顶 + 10` 的较大值),空状态居中输入框时不动它;
|
|
1182
|
+
挂载、`refresh()` 轮询与窗口 resize 都会重算。拖拽时仍可自由移动,松手后会
|
|
1183
|
+
自动避让 —— **可以拖到输入框上,但不能停在那里**。
|
|
1184
|
+
- 注释里记录这两个坑:`window.addEventListener?.()` 用可选调用,否则精简测试
|
|
1185
|
+
环境的 `window` stub 会让整个挂载失败。
|
|
1186
|
+
|
|
1187
|
+
### Tests
|
|
1188
|
+
- 新增回归测试 1 条(`the widget lets clicks through and keeps clear of the composer`),
|
|
1189
|
+
静态校验上述 CSS 与避让逻辑;`node --test` 105/105 通过。
|
|
1190
|
+
|
|
1191
|
+
---
|
|
1192
|
+
|
|
1193
|
+
## [0.3.1] — 2026-09-29
|
|
1194
|
+
|
|
1195
|
+
### Changed
|
|
1196
|
+
- **猪不再被面板挤走,也不再被面板衬着。** 之前猪是面板里的第一个元素,展开时
|
|
1197
|
+
它被顶到一张 452px 高卡片的顶端 —— 窗口不够高时直接飞出屏幕上边缘
|
|
1198
|
+
(400px 窗口实测:`top: -24`,只剩两只脚)。现在猪是面板的**兄弟节点**而不是子节点:
|
|
1199
|
+
|
|
1200
|
+
```
|
|
1201
|
+
host [ data-dsh-pig ] ← 固定在右下角
|
|
1202
|
+
├── .dp-card 面板:内容 + 六图标(收起时整体 hidden)
|
|
1203
|
+
└── .dp-scene 猪,永远在底部
|
|
1204
|
+
```
|
|
1205
|
+
|
|
1206
|
+
面板只能向上生长,猪的像素位置在两种状态下**完全相同**(实测 400 / 720 / 320px
|
|
1207
|
+
窗口下 `movedX = movedY = 0`),而且展开时猪也是全透明的 —— 不再是深色卡片上的一只猪。
|
|
1208
|
+
- **猪的背景透明**。收起态原来的深色圆角胶囊(`background:rgba(22,26,35,.9)` + 边框 +
|
|
1209
|
+
投影)全部去掉,只剩 emoji 本身加一层柔和投影。
|
|
1210
|
+
- **HUD 改成浅色胶囊**。名字/金币/健康原来是为深色卡片配的浅灰字,猪搬到面板外之后
|
|
1211
|
+
裸在页面背景上几乎看不见。
|
|
1212
|
+
- **面板限高** `max-height: calc(100vh - 26px - var(--scene-open))`(26 = 18 底部内缩 + 8 间距),
|
|
1213
|
+
内容区加 `flex:1 1 auto; min-height:0`,短窗口下面板和内容都不会被切。
|
|
1214
|
+
- **尺寸参数化**。猪的大小、它脚下的留白、场景高度、面板限高原本是四组写死的数字,
|
|
1215
|
+
现在统一由 `--pig-size` / `--pig-gap-below` / `--scene-open` 三个变量推导 ——
|
|
1216
|
+
改一个数不会再让别处对不上。
|
|
1217
|
+
- **猪放大到 56px**(原 38px,包围盒 47×38 → 70×56)。场景高度自动跟着变成 68/132。
|
|
1218
|
+
- 形变动画去掉 `translateX(-50%)` 居中偏移(猪现在是普通 flex 子元素)。
|
|
1219
|
+
|
|
1220
|
+
### Fixed
|
|
1221
|
+
- **收起状态依然显示图标栏和 HUD**。`hidden` 属性只对没有自有 `display` 的元素有效,
|
|
1222
|
+
而 `.dp-bar{display:grid}` 和 `.dp-hud{display:flex}` 与 UA 样式表的
|
|
1223
|
+
`[hidden]{display:none}` **同权重**(都是 0,1,0),我的样式表在后面 → 我的赢。
|
|
1224
|
+
结果:JS 里 `bar.hidden = true` 是对的,浏览器里图标栏照画不误,
|
|
1225
|
+
和收起状态的深色猪胶囊叠在一起。
|
|
1226
|
+
加了显式的 `[data-dsh-pig] .dp-x[hidden]{display:none}` 规则。
|
|
1227
|
+
**教训:`el.hidden === true` 的断言证明不了元素不可见** —— 103 个测试全绿,
|
|
1228
|
+
而真实浏览器里它是坏的。已补一条静态守卫测试,并新增真实浏览器预览台。
|
|
1229
|
+
- **web 路由永远不注册**。原代码在 `apply()` 时裸调 `ctx.get('webServer')`,
|
|
1230
|
+
拿到 undefined 就被守卫静默跳过。profile 激活时该服务尚未挂上,
|
|
1231
|
+
所以 `/dsh-pig/state` 和 `/dsh-pig/act` 一直 404 —— 而插件自己报告激活成功。
|
|
1232
|
+
改用 `ctx.inject(['webServer'], …)` 等待服务就绪(DSH 的
|
|
1233
|
+
`client/connection` 与 `client/modules` 就是这么做)。
|
|
1234
|
+
|
|
1235
|
+
### Added
|
|
1236
|
+
- **`tools/preview.html`** —— 在真实浏览器里渲染客户端半边的预览台:
|
|
1237
|
+
伪造 `__ModuleLoader__` 和 `fetch`,喂一份快照给 `client.js`,
|
|
1238
|
+
不连真实 DSH 就能看收起/展开两种状态和全部六个页签。
|
|
1239
|
+
这次的两个 UI bug 都是靠它才看见的。
|
|
1240
|
+
|
|
1241
|
+
---
|
|
1242
|
+
|
|
1243
|
+
## [0.3.0] — 2026-09-29
|
|
1244
|
+
|
|
1245
|
+
### Added
|
|
1246
|
+
- **六个图标的面板**,照 QQ 宠物原版布局重做:宠物在上,奶油色图标栏在下,
|
|
1247
|
+
内容区在图标栏之下。点图标切换,点了就展开,不用敲命令。
|
|
1248
|
+
- `状态` · `学习` · `打工` · `商店` · `旅行` · `背包`
|
|
1249
|
+
- **学习系统**(QQ 宠物 9 门课 × 3 学段):语文/数学/政治 → 智力,
|
|
1250
|
+
美术/音乐/礼仪 → 魅力,体育/武术/劳动 → 武力。上课先交学费,
|
|
1251
|
+
到点后涨属性、记课时。三学段:小学(2 分钟 / 10 金币 / +1)、
|
|
1252
|
+
大学(6 分钟 / 45 / +2)、研究生(15 分钟 / 130 / +4)。
|
|
1253
|
+
- **旅行系统**:郊游 / 名山大川 / 看海 / 出国,出发扣钱,回来
|
|
1254
|
+
带回**纪念品**进收藏册(每趟目的地有 3 种纪念品,轮换发放以保证都能收集到)。
|
|
1255
|
+
- **智魅武三维**(QQ 宠物 `PetInfo.intel/charm/strong`)。
|
|
1256
|
+
- **纪念品收藏册**。
|
|
1257
|
+
- **属性条带标签**(照原版「宠物档案」:饱食/心情/清洁/健康 各一条带名字的横条)。
|
|
1258
|
+
- **`normalize()` 视图模型层**:客户端收到的任何字段缺失都填默认值,
|
|
1259
|
+
不再可能显示 `undefined`。
|
|
1260
|
+
- **版本错配提示**:宿主是旧版时,面板顶部明确写出"重启 dsh 之后才会出现",
|
|
1261
|
+
而不是默默留空。
|
|
1262
|
+
|
|
1263
|
+
### Changed
|
|
1264
|
+
- **`work` 记录统一为 `activity`**:打工 / 学习 / 旅行同构(`kind` + `key` + `endsAt`),
|
|
1265
|
+
"猪在不在家"从此只有一个判断来源,`decay()` 也只有一个结账点。
|
|
1266
|
+
- 状态字段 `canWork` / `workBlocked` → `canGoOut` / `awayBlocked`。
|
|
1267
|
+
- 拒绝原因 `working` → `away`(涵盖三种外出)。
|
|
1268
|
+
- 开局金币 20 → **60**(够上一次小学课)。
|
|
1269
|
+
- 存档版本 **3 → 4**,v3 的 `work` 记录会自动升格为 `activity`。
|
|
1270
|
+
|
|
1271
|
+
### Fixed
|
|
1272
|
+
- **未孵蛋时面板崩溃**:`renderContent()` 在 `pig === null` 时仍然读了
|
|
1273
|
+
`view.pig.illness`,抛 `TypeError`。所有告警块现在都以 `pig !== null` 守卫。
|
|
1274
|
+
- **死亡时客户端不禁用按钮**:客户端原先只信宿主给的 `ready` 标志,
|
|
1275
|
+
现在自己也检查 `view.dead`(纵深防御)。
|
|
1276
|
+
- **还魂丹没有 `kind` 字段**,在背包里被显示成"食物/洗浴"。
|
|
1277
|
+
- **去掉装饰性背景**:天空草地渐变、云、草全删了 —— 猪不需要背景。
|
|
1278
|
+
|
|
1279
|
+
---
|
|
1280
|
+
|
|
1281
|
+
## [0.2.0] — 2026-09-29
|
|
1282
|
+
|
|
1283
|
+
### Added
|
|
1284
|
+
- **打工系统**:打零工(1 分钟 / 12 金币)、搬砖(3 分钟 / 42)、
|
|
1285
|
+
上班(10 分钟 / 150)。外出期间不能喂食洗澡(可以摸摸),消耗加倍,
|
|
1286
|
+
可以召回但没钱。
|
|
1287
|
+
- **疾病链**(照 QQ 宠物 v1.2.4 逆向):三条链各四期
|
|
1288
|
+
- 感冒 → 发烧 → 重感冒 → 肺炎
|
|
1289
|
+
- 咳嗽 → 支气管炎 → 哮喘 → 肺结核
|
|
1290
|
+
- 肚子胀 → 胃炎 → 胃溃疡 → 胃癌
|
|
1291
|
+
- **健康值 5 点**(原版尺度),每期疾病扣一点,归零即死亡。
|
|
1292
|
+
- **对症下药**:四档药品,必须匹配当前病期,吃错无效也不消耗。
|
|
1293
|
+
- **死亡与复活**:等级、经验、金币、收藏全部保留,还魂丹(150 金币)救回。
|
|
1294
|
+
- **金币经济 + 商店 + 背包**(9 种商品)。
|
|
1295
|
+
- **清洁度**:会随时间衰减,低于阈值触发"该洗澡了"。
|
|
1296
|
+
- 心情新增 `sick` / `working` / `dead` 三态。
|
|
1297
|
+
|
|
1298
|
+
### Changed
|
|
1299
|
+
- 存档版本 **2 → 3**;v1/v2 存档自动补上清洁度、健康、金币、背包。
|
|
1300
|
+
- 被动事件与主动动作彻底分开:`feed()` 只吃被动事件,用户动作走新的 `act()`。
|
|
1301
|
+
|
|
1302
|
+
### Fixed
|
|
1303
|
+
- **拒绝操作谎报成功**:`{ ...result, ...snapshot(store) }` 里 snapshot 的
|
|
1304
|
+
`ok: true` 覆盖了操作结果的 `ok: false`,导致冷却中/打工中的操作返回成功。
|
|
1305
|
+
改为快照在前、判定在后。
|
|
1306
|
+
- **动作接口响应漏了 `actions` 字段**,点完按钮冷却状态不刷新(按钮不变灰)。
|
|
1307
|
+
- **没孵蛋时按钮点了没反应** —— 面板里加了「🥚 孵一只」按钮,
|
|
1308
|
+
从此从装到养一次键盘都不用碰。
|
|
1309
|
+
- 按钮回调依赖 `this.getAttribute()`,改用闭包捕获(`this` 绑定被包装就废)。
|
|
1310
|
+
|
|
1311
|
+
---
|
|
1312
|
+
|
|
1313
|
+
## [0.1.0] — 2026-09-29
|
|
1314
|
+
|
|
1315
|
+
### Added
|
|
1316
|
+
- 第一版:`/pig` 斜杠命令 + 右下角悬浮猪。
|
|
1317
|
+
- 照顾动作:喂食 / 洗澡 / 玩耍 / 摸摸(各自独立冷却)。
|
|
1318
|
+
- 成长阶梯 7 级(猪蛋 → 野猪王),经验来自真实工作
|
|
1319
|
+
(完成回合 +5 · 发消息 +2 · 工具调用 +3 · 报错也长肉)。
|
|
1320
|
+
- 体重系统(1.2 kg 起步,吃一口涨一点)。
|
|
1321
|
+
- 心情系统(饿 / 困 / 开心 / 孤单,按真实时间衰减)。
|
|
1322
|
+
- 原子写存档 + 1.5 秒节流。
|
|
1323
|
+
- 客户端动画与粒子特效;`apply()` 全程 try/catch,激活期绝不抛异常。
|
|
1324
|
+
|
|
1325
|
+
### Fixed
|
|
1326
|
+
- **`/pig hatch` 之后仍是「猪蛋」** —— 蛋壳都裂开了还显示是蛋。
|
|
1327
|
+
新增 `hatchEgg()`,孵出来直接是 Lv.2 小猪崽,并补了回归测试。
|
|
1328
|
+
|
|
1329
|
+
---
|
|
1330
|
+
|
|
1331
|
+
## 版本对照:DSH 运行时
|
|
1332
|
+
|
|
1333
|
+
| dsh-pig | DSH 运行时 | 说明 |
|
|
1334
|
+
|---|---|---|
|
|
1335
|
+
| 0.3.0 | 0.2.0-rc.1 | 当前 |
|
|
1336
|
+
| 0.2.0 | 0.2.0-rc.1 | |
|
|
1337
|
+
| 0.1.0 | 0.2.0-rc.1 | |
|
|
1338
|
+
|
|
1339
|
+
## 存档版本
|
|
1340
|
+
|
|
1341
|
+
| 存档 | 引入版本 | 迁移 |
|
|
1342
|
+
|---|---|---|
|
|
1343
|
+
| v1 | 0.1.0 | 无清洁度 / 健康 / 金币 / 背包 |
|
|
1344
|
+
| v2 | 0.1.0 中期 | 加清洁度、冷却 |
|
|
1345
|
+
| v3 | 0.2.0 | 加健康、金币、背包、疾病 |
|
|
1346
|
+
| v4 | 0.3.0 | `work` → `activity`,加智魅武、课时、纪念品 |
|
|
1347
|
+
|
|
1348
|
+
每次迁移都有测试覆盖,不会丢数据(等级、经验、金币、收藏都保留)。
|