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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* 居民卡页签(B9,照动森居民卡 + animal-island-ui Form 页的卡片)。
|
|
4
|
+
*
|
|
5
|
+
* 淡色点点底的卡(女孩粉、男孩蓝):左边头像,右边名字和等级;下面「标签:值」
|
|
6
|
+
* 一行行(生日 / 星座 / 性格 / 口头禅),签名单独一个气泡,最底下一行收藏数。
|
|
7
|
+
* 口头禅和签名旁边的铅笔按钮就地改,改的时候轮询不重画(见 panel.js)。
|
|
8
|
+
* 加冕在主屏自己的 App 里(tabs/crown.js);加冕后卡上多一行「形态」。
|
|
9
|
+
* @module dsh-piggy/client/tabs/card
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { ART_URL } from '../constants.js'
|
|
13
|
+
import { button, el } from '../dom.js'
|
|
14
|
+
|
|
15
|
+
/** How long each editable field may be (mirrors data/profile.js). */
|
|
16
|
+
var LIMITS = { catchphrase: 6, motto: 24 }
|
|
17
|
+
|
|
18
|
+
export function renderCardTab(ui) {
|
|
19
|
+
var p = ui.view.pig
|
|
20
|
+
var profile = ui.view.profile
|
|
21
|
+
if (p === null) return
|
|
22
|
+
if (profile === null) {
|
|
23
|
+
ui.content.appendChild(el('div', 'dp-empty', '重启 dsh 之后才有居民卡'))
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
var card = el('div', 'dp-vcard')
|
|
27
|
+
card.setAttribute('data-sex', p.sex !== null ? p.sex.key : 'none')
|
|
28
|
+
|
|
29
|
+
var top = el('div', 'dp-vcard-top')
|
|
30
|
+
var avatar = el('div', 'dp-vcard-avatar')
|
|
31
|
+
if (p.stage.art !== null) {
|
|
32
|
+
var img = /** @type {HTMLImageElement} */ (el('img', 'dp-vcard-img'))
|
|
33
|
+
img.src = ART_URL + p.stage.art + '.svg'
|
|
34
|
+
img.alt = ''
|
|
35
|
+
avatar.appendChild(img)
|
|
36
|
+
} else {
|
|
37
|
+
avatar.appendChild(el('span', 'dp-vcard-e', p.stage.emoji))
|
|
38
|
+
}
|
|
39
|
+
top.appendChild(avatar)
|
|
40
|
+
var who = el('div', 'dp-vcard-who')
|
|
41
|
+
who.appendChild(el('b', 'dp-vcard-name', p.name + (p.sex !== null ? ' ' + p.sex.symbol : '')))
|
|
42
|
+
who.appendChild(el('span', 'dp-vcard-sub', 'Lv.' + p.level.level + ' ' + p.level.titleEmoji + p.level.titleLabel))
|
|
43
|
+
who.appendChild(el('span', 'dp-vcard-sub', p.stage.label))
|
|
44
|
+
top.appendChild(who)
|
|
45
|
+
card.appendChild(top)
|
|
46
|
+
|
|
47
|
+
card.appendChild(field('生日', profile.birthday))
|
|
48
|
+
if (profile.zodiac !== null) card.appendChild(field('星座', profile.zodiac.emoji + ' ' + profile.zodiac.label))
|
|
49
|
+
if (profile.personality !== null) card.appendChild(field('性格', profile.personality.emoji + ' ' + profile.personality.label))
|
|
50
|
+
var forms = ui.view.forms
|
|
51
|
+
var worn = forms === null ? null : forms.forms.find(function (f) { return f.current }) || null
|
|
52
|
+
if (worn !== null) card.appendChild(field('形态', worn.emoji + ' ' + worn.label))
|
|
53
|
+
card.appendChild(editableField(ui, 'catchphrase', '口头禅', profile.catchphrase))
|
|
54
|
+
card.appendChild(editableField(ui, 'motto', '签名', profile.motto))
|
|
55
|
+
|
|
56
|
+
var c = profile.counts
|
|
57
|
+
card.appendChild(el('div', 'dp-vcard-foot',
|
|
58
|
+
'养了 ' + c.days + ' 天 · 证书 ' + c.certificates + ' · 纪念品 ' + c.souvenirs + ' · 毕业 ' + c.graduations))
|
|
59
|
+
ui.content.appendChild(card)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** 「标签:值」 —— the value in a cream pill, like the reference form. */
|
|
63
|
+
function field(label, value) {
|
|
64
|
+
var row = el('div', 'dp-vcard-row')
|
|
65
|
+
row.appendChild(el('span', 'dp-vcard-label', label + ':'))
|
|
66
|
+
row.appendChild(el('span', 'dp-vcard-value', value))
|
|
67
|
+
return row
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* A field the owner can change in place. The motto gets its own speech
|
|
72
|
+
* bubble rather than a pill: it is the pig talking.
|
|
73
|
+
*/
|
|
74
|
+
function editableField(ui, key, label, value) {
|
|
75
|
+
var editing = ui.cardEdit !== null && ui.cardEdit.field === key
|
|
76
|
+
var row = el('div', 'dp-vcard-row' + (key === 'motto' ? ' dp-vcard-motto-row' : ''))
|
|
77
|
+
row.appendChild(el('span', 'dp-vcard-label', label + ':'))
|
|
78
|
+
if (editing) {
|
|
79
|
+
var input = /** @type {HTMLInputElement} */ (el('input', 'dp-input dp-vcard-input'))
|
|
80
|
+
input.value = ui.cardEdit.draft
|
|
81
|
+
input.maxLength = LIMITS[key]
|
|
82
|
+
input.setAttribute('data-card-input', key)
|
|
83
|
+
input.addEventListener('input', function () { ui.cardEdit = { field: key, draft: input.value } })
|
|
84
|
+
var save = button('dp-mini', { 'data-card-save': key }, function () {
|
|
85
|
+
var text = (ui.cardEdit === null ? '' : ui.cardEdit.draft).trim()
|
|
86
|
+
ui.cardEdit = null
|
|
87
|
+
if (text !== '') ui.send(key, { text: text })
|
|
88
|
+
ui.renderContent()
|
|
89
|
+
})
|
|
90
|
+
save.textContent = '好'
|
|
91
|
+
var cancel = button('dp-mini dp-mini-plain', { 'data-card-cancel': key }, function () {
|
|
92
|
+
ui.cardEdit = null
|
|
93
|
+
ui.renderContent()
|
|
94
|
+
})
|
|
95
|
+
cancel.textContent = '算了'
|
|
96
|
+
row.appendChild(input)
|
|
97
|
+
row.appendChild(save)
|
|
98
|
+
row.appendChild(cancel)
|
|
99
|
+
return row
|
|
100
|
+
}
|
|
101
|
+
row.appendChild(el('span', key === 'motto' ? 'dp-vcard-value dp-vcard-motto' : 'dp-vcard-value', key === 'motto' ? '「' + value + '」' : value))
|
|
102
|
+
var pencil = button('dp-vcard-edit', { 'data-card-edit': key }, function () {
|
|
103
|
+
ui.cardEdit = { field: key, draft: value }
|
|
104
|
+
ui.renderContent()
|
|
105
|
+
})
|
|
106
|
+
pencil.textContent = '✏️'
|
|
107
|
+
pencil.title = '改' + label
|
|
108
|
+
row.appendChild(pencil)
|
|
109
|
+
return row
|
|
110
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* 加冕 App:每种形态一块(data/evolution.js 的 FORMS,猪猪王是第一种,以后还会加)。
|
|
4
|
+
* 左边是那个形态的立绘,右边名字和条件,条件一条条打勾,齐了就能点加冕。
|
|
5
|
+
* 已经是的那种标「当前形态」。
|
|
6
|
+
* @module dsh-piggy/client/tabs/crown
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ART_URL } from '../constants.js'
|
|
10
|
+
import { button, el } from '../dom.js'
|
|
11
|
+
|
|
12
|
+
export function renderCrownTab(ui) {
|
|
13
|
+
var forms = ui.view.forms
|
|
14
|
+
if (forms === null) {
|
|
15
|
+
ui.content.appendChild(el('div', 'dp-empty', '重启 dsh 之后才有加冕'))
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
if (ui.view.dead) ui.content.appendChild(el('div', 'dp-empty', '它走了,救回来才能加冕'))
|
|
19
|
+
for (var f = 0; f < forms.forms.length; f += 1) ui.content.appendChild(formBlock(ui, forms.forms[f]))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** One form: its picture, its conditions as ticked chips, and the button once they are all met. */
|
|
23
|
+
function formBlock(ui, form) {
|
|
24
|
+
var box = el('div', form.current ? 'dp-crown dp-crown-now' : 'dp-crown')
|
|
25
|
+
box.setAttribute('data-form', form.key)
|
|
26
|
+
var top = el('div', 'dp-crown-top')
|
|
27
|
+
var pic = el('div', 'dp-crown-pic')
|
|
28
|
+
if (form.art !== '') {
|
|
29
|
+
var img = /** @type {HTMLImageElement} */ (el('img', 'dp-crown-img'))
|
|
30
|
+
img.src = ART_URL + form.art + '.svg'
|
|
31
|
+
img.alt = ''
|
|
32
|
+
pic.appendChild(img)
|
|
33
|
+
} else {
|
|
34
|
+
pic.appendChild(el('span', null, form.emoji))
|
|
35
|
+
}
|
|
36
|
+
top.appendChild(pic)
|
|
37
|
+
var side = el('div', 'dp-crown-side')
|
|
38
|
+
side.appendChild(el('div', 'dp-crown-head', form.emoji + ' ' + form.label))
|
|
39
|
+
if (form.current) {
|
|
40
|
+
side.appendChild(el('div', 'dp-crown-done', '✓ 当前形态'))
|
|
41
|
+
} else {
|
|
42
|
+
var chips = el('div', 'dp-crown-reqs')
|
|
43
|
+
for (var r = 0; r < form.requirements.length; r += 1) {
|
|
44
|
+
var row = form.requirements[r]
|
|
45
|
+
chips.appendChild(el('span', row.met ? 'dp-crown-req dp-crown-ok' : 'dp-crown-req',
|
|
46
|
+
(row.met ? '✓ ' : '✗ ') + row.label + ' ' + Math.min(row.have, row.need) + '/' + row.need))
|
|
47
|
+
}
|
|
48
|
+
side.appendChild(chips)
|
|
49
|
+
}
|
|
50
|
+
top.appendChild(side)
|
|
51
|
+
box.appendChild(top)
|
|
52
|
+
if (!form.current) {
|
|
53
|
+
var go = button('dp-btn dp-btn-wide', { 'data-crown': form.key }, function () { ui.send('crown', { form: form.key }) })
|
|
54
|
+
go.textContent = form.ready ? '👑 加冕' : '条件齐了就能加冕'
|
|
55
|
+
go.disabled = !form.ready
|
|
56
|
+
box.appendChild(go)
|
|
57
|
+
}
|
|
58
|
+
return box
|
|
59
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* 调试页签。
|
|
4
|
+
*
|
|
5
|
+
* 仅开发者模式可见:改数值、改时间、一键拿齐。
|
|
6
|
+
* @module dsh-piggy/client/tabs/dev
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { button, el } from '../dom.js'
|
|
10
|
+
|
|
11
|
+
export function renderDevTab(ui) {
|
|
12
|
+
ui.content.appendChild(el('div', 'dp-dev-note', '🔧 开发者模式 · 构建 v' + (ui.view.version === '' ? '未知' : ui.view.version) + ' · Ctrl+Shift+D 关闭'))
|
|
13
|
+
if (ui.view.pig !== null && ui.view.pig.ageForced) {
|
|
14
|
+
ui.content.appendChild(el('div', 'dp-dev-note',
|
|
15
|
+
'⚠️ 年龄是调试改的(HUD 上有 🔧)—— 按「⏪ 年龄归零」才会重新按真实时间算'))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var p = ui.view.pig
|
|
19
|
+
if (p === null) {
|
|
20
|
+
ui.content.appendChild(el('div', 'dp-empty', '还没有猪。先「拆开纸盒」再调。'))
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A row of small buttons under a caption. */
|
|
25
|
+
function group(title, entries) {
|
|
26
|
+
var head = el('div', 'dp-title')
|
|
27
|
+
head.appendChild(el('b', null, title))
|
|
28
|
+
ui.content.appendChild(head)
|
|
29
|
+
var wrap = el('div', 'dp-dev-row')
|
|
30
|
+
for (var i = 0; i < entries.length; i += 1) {
|
|
31
|
+
(function (entry) {
|
|
32
|
+
var btn = button('dp-mini dp-dev-btn', { 'data-dev': entry.key }, function () { entry.run() })
|
|
33
|
+
btn.textContent = entry.label
|
|
34
|
+
wrap.appendChild(btn)
|
|
35
|
+
})(entries[i])
|
|
36
|
+
}
|
|
37
|
+
ui.content.appendChild(wrap)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
var patch = function (body) { ui.send('dev', { patch: body }) }
|
|
41
|
+
|
|
42
|
+
group('状态', [
|
|
43
|
+
{ key: 'full', label: '😊 满状态', run: function () { patch({ satiety: 100, happiness: 100, cleanliness: 100, health: 5 }) } },
|
|
44
|
+
{ key: 'hungry', label: '🍎 饿', run: function () { patch({ satiety: 10 }) } },
|
|
45
|
+
{ key: 'dirty', label: '🫧 脏', run: function () { patch({ cleanliness: 10 }) } },
|
|
46
|
+
{ key: 'lonely', label: '🥺 孤单', run: function () { patch({ happiness: 10 }) } },
|
|
47
|
+
{ key: 'sleepy', label: '💤 困', run: function () { patch({ satiety: 90, happiness: 90, cleanliness: 90 }) } },
|
|
48
|
+
])
|
|
49
|
+
|
|
50
|
+
// Five chains since B3: stage 1 of each, the last stage of one, and a cure.
|
|
51
|
+
group('生病', [
|
|
52
|
+
{ key: 'cold1', label: '🤧 感冒', run: function () { patch({ illness: { chain: 0, stage: 1 }, health: 4 }) } },
|
|
53
|
+
{ key: 'cough1', label: '😷 咳嗽', run: function () { patch({ illness: { chain: 1, stage: 1 }, health: 4 }) } },
|
|
54
|
+
{ key: 'belly1', label: '🤢 肚子胀', run: function () { patch({ illness: { chain: 2, stage: 1 }, health: 4 }) } },
|
|
55
|
+
{ key: 'dizzy1', label: '😵 头晕', run: function () { patch({ illness: { chain: 3, stage: 1 }, health: 4 }) } },
|
|
56
|
+
{ key: 'skin1', label: '🩹 瘙痒', run: function () { patch({ illness: { chain: 4, stage: 1 }, health: 4 }) } },
|
|
57
|
+
{ key: 'cold4', label: '☠️ 肺炎', run: function () { patch({ illness: { chain: 0, stage: 4 }, health: 1 }) } },
|
|
58
|
+
{ key: 'cure', label: '💚 治好', run: function () { patch({ illness: null, health: 5 }) } },
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
// The body follows the level since B2: these jump straight to each stage.
|
|
62
|
+
group('等级', [
|
|
63
|
+
{ key: 'box', label: '📦 纸盒', run: function () { patch({ hatched: false }) } },
|
|
64
|
+
{ key: 'lv1', label: '幼年 Lv1', run: function () { patch({ hatched: true, level: 1 }) } },
|
|
65
|
+
{ key: 'lv10', label: '青年 Lv10', run: function () { patch({ level: 10 }) } },
|
|
66
|
+
{ key: 'lv40', label: '成年 Lv40', run: function () { patch({ level: 40 }) } },
|
|
67
|
+
{ key: 'lv60', label: '满级 Lv60', run: function () { patch({ level: 60 }) } },
|
|
68
|
+
{ key: 'real', label: '⏪ 天数归零', run: function () { ui.send('ageFromNow') } },
|
|
69
|
+
])
|
|
70
|
+
|
|
71
|
+
group('资源', [
|
|
72
|
+
{ key: 'coin100', label: '🪙 +100', run: function () { patch({ coins: p.coins + 100 }) } },
|
|
73
|
+
{ key: 'coin999', label: '🪙 9999', run: function () { patch({ coins: 9999 }) } },
|
|
74
|
+
{ key: 'traits', label: '🧠+5 ✨+5 💪+5', run: function () { patch({ traits: { intel: 5, charm: 5, strong: 5 } }) } },
|
|
75
|
+
{ key: 'all', label: '🎁 一键拿齐', run: function () { ui.send('giveAll') } },
|
|
76
|
+
])
|
|
77
|
+
|
|
78
|
+
group('时间', [
|
|
79
|
+
{ key: 'real', label: '×1 真实', run: function () { ui.send('timeScale', { scale: 1 }) } },
|
|
80
|
+
{ key: 'fast12', label: '×12', run: function () { ui.send('timeScale', { scale: 12 }) } },
|
|
81
|
+
{ key: 'fast30', label: '×30', run: function () { ui.send('timeScale', { scale: 30 }) } },
|
|
82
|
+
{ key: 'fast60', label: '×60', run: function () { ui.send('timeScale', { scale: 60 }) } },
|
|
83
|
+
])
|
|
84
|
+
|
|
85
|
+
group('生死', [
|
|
86
|
+
{ key: 'kill', label: '💀 弄死', run: function () { patch({ dead: true }) } },
|
|
87
|
+
{ key: 'revive', label: '✨ 复活', run: function () { patch({ dead: false, health: 5 }) } },
|
|
88
|
+
{ key: 'adopt', label: '📦 领养', run: function () { ui.send('adopt') } },
|
|
89
|
+
{ key: 'reset', label: '🔄 重置', run: function () { ui.send('reset') } },
|
|
90
|
+
])
|
|
91
|
+
|
|
92
|
+
group('面板', [
|
|
93
|
+
{ key: 'open', label: '展开/收起', run: function () { ui.setOpen(ui.host.getAttribute('data-open') !== 'true') } },
|
|
94
|
+
{ key: 'away1', label: '⏩ +1 小时', run: function () { patch({ __advanceMs: 3600000 }) } },
|
|
95
|
+
{ key: 'away24', label: '⏩ +1 天', run: function () { patch({ __advanceMs: 86400000 }) } },
|
|
96
|
+
])
|
|
97
|
+
|
|
98
|
+
ui.content.appendChild(el('div', 'dp-dev-note',
|
|
99
|
+
'当前:' + p.stage.label + ' · 健康 ' + p.health + ' · 🪙 ' + p.coins
|
|
100
|
+
+ (p.illness === null ? '' : ' · ' + p.illness.name)))
|
|
101
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* 主屏(B9,照动森手机):打开面板先看到一格格 App 方块,点进去是那个页签,
|
|
4
|
+
* 页签顶上「‹」回主屏。原来挂在底部图标上的提醒,改挂在方块左上角。
|
|
5
|
+
* @module dsh-piggy/client/tabs/home
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { el } from '../dom.js'
|
|
9
|
+
import { tile, tileGrid } from '../widgets.js'
|
|
10
|
+
|
|
11
|
+
/** One colour per app, so the home screen reads at a glance. */
|
|
12
|
+
var APP_COLOR = {
|
|
13
|
+
status: 'green', card: 'pink', crown: 'purple', study: 'yellow', work: 'orange',
|
|
14
|
+
shop: 'red', travel: 'blue', bag: 'teal', update: 'lime', dev: 'brown',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** The home screen: who the pig is, its money, and one tile per app. */
|
|
18
|
+
export function renderHome(ui, apps) {
|
|
19
|
+
var p = ui.view.pig
|
|
20
|
+
var head = el('div', 'dp-title')
|
|
21
|
+
head.appendChild(el('b', null, p.name + (p.sex !== null ? ' ' + p.sex.symbol : '') + ' Lv.' + p.level.level))
|
|
22
|
+
head.appendChild(el('span', null, '🪙 ' + p.coins))
|
|
23
|
+
ui.content.appendChild(head)
|
|
24
|
+
var grid = tileGrid()
|
|
25
|
+
for (var i = 0; i < apps.length; i += 1) {
|
|
26
|
+
(function (app) {
|
|
27
|
+
grid.appendChild(tile({
|
|
28
|
+
emoji: app.emoji, label: app.label, color: APP_COLOR[app.key] ?? 'blue',
|
|
29
|
+
tag: alertFor(ui, app.key),
|
|
30
|
+
data: { 'data-app': app.key },
|
|
31
|
+
onPick: function () { ui.select(app.key) },
|
|
32
|
+
}))
|
|
33
|
+
})(apps[i])
|
|
34
|
+
}
|
|
35
|
+
ui.content.appendChild(grid)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The little word on an app's corner: what needs looking at in there. The
|
|
40
|
+
* status app speaks for the pig itself (gone, ill, out); the others reuse the
|
|
41
|
+
* alerts the panel already works out for the hidden icon bar.
|
|
42
|
+
*/
|
|
43
|
+
function alertFor(ui, key) {
|
|
44
|
+
var p = ui.view.pig
|
|
45
|
+
if (key === 'status') {
|
|
46
|
+
if (ui.view.dead) return '走了'
|
|
47
|
+
if (p.illness !== null) return '生病'
|
|
48
|
+
if (ui.view.activity !== null) return '在外面'
|
|
49
|
+
return ''
|
|
50
|
+
}
|
|
51
|
+
var icon = ui.icons[key]
|
|
52
|
+
return icon !== undefined && icon.getAttribute('data-alert') === 'true' ? '!' : ''
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* An app's top row: 「‹」 back to the home screen, the app's name, and one grey
|
|
57
|
+
* line on the right (the shop's money, say).
|
|
58
|
+
*/
|
|
59
|
+
export function appHeader(ui, app, info) {
|
|
60
|
+
var row = el('div', 'dp-drill dp-app-head')
|
|
61
|
+
var back = el('button', 'dp-drill-back')
|
|
62
|
+
back.setAttribute('data-home', 'true')
|
|
63
|
+
back.textContent = '‹'
|
|
64
|
+
back.addEventListener('click', function (event) {
|
|
65
|
+
if (event && typeof event.stopPropagation === 'function') event.stopPropagation()
|
|
66
|
+
ui.select('home')
|
|
67
|
+
})
|
|
68
|
+
row.appendChild(back)
|
|
69
|
+
row.appendChild(el('b', 'dp-drill-title', app.emoji + ' ' + app.label))
|
|
70
|
+
if (info) row.appendChild(el('span', 'dp-drill-info', info))
|
|
71
|
+
ui.content.appendChild(row)
|
|
72
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* 商店页签(B8:动森手机式方块)。
|
|
4
|
+
*
|
|
5
|
+
* 第一层:六个货架方块。第二层:这个货架的货,点方块就是买。
|
|
6
|
+
* @module dsh-piggy/client/tabs/shop
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { KIND_ORDER, KIND_TITLE } from '../constants.js'
|
|
10
|
+
import { el } from '../dom.js'
|
|
11
|
+
import { num } from '../values.js'
|
|
12
|
+
import { drillHeader, drillTo, tile, tileGrid } from '../widgets.js'
|
|
13
|
+
|
|
14
|
+
/** One colour per shelf, so the inner layer still says which shelf it is. */
|
|
15
|
+
export var SHELF_COLOR = { food: 'red', bath: 'teal', toy: 'yellow', dress: 'pink', medicine: 'green', revive: 'purple' }
|
|
16
|
+
|
|
17
|
+
/** A shelf title 「<emoji> 食物」 split into its emoji and its name. */
|
|
18
|
+
export function shelfParts(kind) {
|
|
19
|
+
var title = KIND_TITLE[kind] ?? kind
|
|
20
|
+
var space = title.indexOf(' ')
|
|
21
|
+
return space < 0 ? ['🛒', title] : [title.slice(0, space), title.slice(space + 1)]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function renderShopTab(ui) {
|
|
25
|
+
if (ui.view.shop.length === 0) {
|
|
26
|
+
ui.content.appendChild(el('div', 'dp-empty', '宿主还没提供货架。'))
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
var coins = '🪙 ' + ui.view.pig.coins
|
|
30
|
+
var shelf = ui.drill.shop
|
|
31
|
+
if (shelf === null || KIND_ORDER.indexOf(shelf) < 0) {
|
|
32
|
+
renderShelves(ui)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
var parts = shelfParts(shelf)
|
|
36
|
+
drillHeader(ui, 'shop', parts[0] + ' ' + parts[1], coins)
|
|
37
|
+
var grid = tileGrid()
|
|
38
|
+
var items = ui.view.shop.filter(function (item) { return item.kind === shelf })
|
|
39
|
+
for (var i = 0; i < items.length; i += 1) grid.appendChild(itemTile(ui, items[i], SHELF_COLOR[shelf]))
|
|
40
|
+
ui.content.appendChild(grid)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The top layer; its title row (with the money) is the app header. */
|
|
44
|
+
function renderShelves(ui) {
|
|
45
|
+
var grid = tileGrid()
|
|
46
|
+
for (var k = 0; k < KIND_ORDER.length; k += 1) {
|
|
47
|
+
(function (kind) {
|
|
48
|
+
var items = ui.view.shop.filter(function (item) { return item.kind === kind })
|
|
49
|
+
if (items.length === 0) return
|
|
50
|
+
var parts = shelfParts(kind)
|
|
51
|
+
var needed = items.some(function (item) { return item.needed })
|
|
52
|
+
grid.appendChild(tile({
|
|
53
|
+
emoji: parts[0], label: parts[1], color: SHELF_COLOR[kind] ?? 'blue',
|
|
54
|
+
tag: needed ? '需要' : '',
|
|
55
|
+
data: { 'data-shelf': kind },
|
|
56
|
+
onPick: function () { drillTo(ui, 'shop', kind) },
|
|
57
|
+
}))
|
|
58
|
+
})(KIND_ORDER[k])
|
|
59
|
+
}
|
|
60
|
+
ui.content.appendChild(grid)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** A thing on the shelf: tap to buy. 家当 says 已拥有 or the level it waits for. */
|
|
64
|
+
function itemTile(ui, item, color) {
|
|
65
|
+
var owned = num(ui.view.inventory[item.key], 0)
|
|
66
|
+
var note = item.price + ' 🪙'
|
|
67
|
+
if (item.owned) note = '已拥有'
|
|
68
|
+
else if (item.kind === 'dress' && item.unlocked === false) note = '🔒 Lv.' + item.level
|
|
69
|
+
return tile({
|
|
70
|
+
emoji: item.emoji, label: item.label, color: color, soft: true, note: note,
|
|
71
|
+
badge: owned > 0 ? '×' + owned : '',
|
|
72
|
+
tag: item.needed ? '需要' : (item.owned && item.worn ? '穿着' : ''),
|
|
73
|
+
dim: !item.owned && (!item.affordable || (item.kind === 'dress' && item.unlocked === false)),
|
|
74
|
+
disabled: item.owned === true,
|
|
75
|
+
data: { 'data-buy': item.key },
|
|
76
|
+
onPick: function () { ui.send('buy', { item: item.key }) },
|
|
77
|
+
})
|
|
78
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* 状态页签。
|
|
4
|
+
*
|
|
5
|
+
* 属性条、三维、体重金币与照顾入口。
|
|
6
|
+
* @module dsh-piggy/client/tabs/status
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { CARE_LABEL, MODES } from '../constants.js'
|
|
10
|
+
import { button, el } from '../dom.js'
|
|
11
|
+
import { labelledBar, pickerPanel } from '../widgets.js'
|
|
12
|
+
|
|
13
|
+
export function renderStatusTab(ui) {
|
|
14
|
+
var p = ui.view.pig
|
|
15
|
+
if (p === null) return
|
|
16
|
+
renderBanners(ui)
|
|
17
|
+
labelledBar(ui, '🍚 饱食', p.satiety, p.satiety + '%')
|
|
18
|
+
labelledBar(ui, '❤️ 心情', p.happiness, p.happiness + '%', 'dp-mood')
|
|
19
|
+
labelledBar(ui, '🫧 清洁', p.cleanliness, p.cleanliness + '%', 'dp-clean')
|
|
20
|
+
labelledBar(ui, '💚 健康', p.healthPercent, p.health + '/' + ui.view.maxHealth, 'dp-health')
|
|
21
|
+
|
|
22
|
+
var traits = el('div', 'dp-traits')
|
|
23
|
+
traits.appendChild(el('span', null, '🧠 智力 ' + p.traits.intel))
|
|
24
|
+
traits.appendChild(el('span', null, '✨ 魅力 ' + p.traits.charm))
|
|
25
|
+
traits.appendChild(el('span', null, '💪 武力 ' + p.traits.strong))
|
|
26
|
+
ui.content.appendChild(traits)
|
|
27
|
+
|
|
28
|
+
var info = el('div', 'dp-row')
|
|
29
|
+
info.appendChild(el('span', null, '⚖️ 体重 ' + p.weight))
|
|
30
|
+
info.appendChild(el('b', null, '🪙 ' + p.coins))
|
|
31
|
+
ui.content.appendChild(info)
|
|
32
|
+
|
|
33
|
+
// 签到进度:一行小字,不抢注意力(礼包攒着的时候顺带说一句)。
|
|
34
|
+
var daily = ui.view.daily
|
|
35
|
+
var dailyLine = el('div', 'dp-row')
|
|
36
|
+
dailyLine.appendChild(el('span', null, '📅 签到'))
|
|
37
|
+
dailyLine.appendChild(el('b', null, '第 ' + daily.signInDay + '/' + daily.cycle + ' 天'
|
|
38
|
+
+ (daily.canSignIn ? ' · 今天还没签' : '')
|
|
39
|
+
+ (daily.unclaimed > 0 ? ' · 🎁 ' + daily.unclaimed : '')))
|
|
40
|
+
ui.content.appendChild(dailyLine)
|
|
41
|
+
|
|
42
|
+
var lvl = el('div', 'dp-row')
|
|
43
|
+
lvl.appendChild(el('span', null, '⭐ 等级'))
|
|
44
|
+
lvl.appendChild(el('b', null, 'Lv.' + p.level.level + ' ' + p.level.titleEmoji + p.level.titleLabel
|
|
45
|
+
+ (p.level.maxed ? ' · 满级' : ' · 还差 ' + Math.ceil(p.level.toNext) + ' 成长')))
|
|
46
|
+
ui.content.appendChild(lvl)
|
|
47
|
+
|
|
48
|
+
var age = el('div', 'dp-row')
|
|
49
|
+
age.appendChild(el('span', null, '🏠 陪伴'))
|
|
50
|
+
age.appendChild(el('b', null, p.ageLabel + (p.ageForced ? ' 🔧' : '') + (p.daysToNextStage === null ? ' · 已长成' : '')))
|
|
51
|
+
ui.content.appendChild(age)
|
|
52
|
+
|
|
53
|
+
var grid = el('div', 'dp-actions')
|
|
54
|
+
for (var i = 0; i < MODES.length; i += 1) {
|
|
55
|
+
(function (key) {
|
|
56
|
+
var info = ui.view.actions[key]
|
|
57
|
+
var shelf = ui.view.care[key] ?? []
|
|
58
|
+
var needsItem = shelf.length > 0
|
|
59
|
+
var btn = button('dp-btn', { 'data-action': key }, function () {
|
|
60
|
+
// Feeding, washing and playing all spend something, so the button
|
|
61
|
+
// opens the pig's bag instead of guessing what to use.
|
|
62
|
+
if (needsItem) {
|
|
63
|
+
ui.picker = ui.picker === key ? null : key
|
|
64
|
+
ui.renderContent()
|
|
65
|
+
} else {
|
|
66
|
+
ui.send(key)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
btn.setAttribute('data-open-picker', ui.picker === key ? 'true' : 'false')
|
|
70
|
+
btn.appendChild(el('span', null, CARE_LABEL[key][1]))
|
|
71
|
+
btn.appendChild(el('span', null, CARE_LABEL[key][0]))
|
|
72
|
+
if (needsItem) btn.appendChild(el('span', 'dp-count', String(shelf.length)))
|
|
73
|
+
// Trust but verify: a dead pig cannot be cared for even if the host
|
|
74
|
+
// forgot to clear its readiness flags.
|
|
75
|
+
if (!info.ready || ui.view.dead) {
|
|
76
|
+
btn.disabled = true
|
|
77
|
+
if (ui.view.dead) btn.appendChild(el('span', 'dp-wait', '—'))
|
|
78
|
+
else if (info.waitSeconds > 0) btn.appendChild(el('span', 'dp-wait', info.waitSeconds + 's'))
|
|
79
|
+
else if (info.blocked === 'away') btn.appendChild(el('span', 'dp-wait', '不在家'))
|
|
80
|
+
}
|
|
81
|
+
grid.appendChild(btn)
|
|
82
|
+
})(MODES[i])
|
|
83
|
+
}
|
|
84
|
+
ui.content.appendChild(grid)
|
|
85
|
+
|
|
86
|
+
if (ui.picker !== null && (ui.view.care[ui.picker] ?? []).length > 0) ui.content.appendChild(pickerPanel(ui, ui.picker))
|
|
87
|
+
|
|
88
|
+
ui.content.appendChild(talkRow(ui))
|
|
89
|
+
|
|
90
|
+
if (p.memories.length > 0) {
|
|
91
|
+
ui.content.appendChild(el('div', 'dp-memo', p.memories.slice(-3).join('\n')))
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* B6: what the pig calls its owner, and 免打扰 — one row, two small controls.
|
|
97
|
+
* While the name is being typed, polls leave the panel alone (see panel.js),
|
|
98
|
+
* so the input keeps its focus.
|
|
99
|
+
*/
|
|
100
|
+
function talkRow(ui) {
|
|
101
|
+
var row = el('div', 'dp-row dp-talk')
|
|
102
|
+
// 用户 2026-10-01:别把称呼印在面板上(「叫你『大爹』」那行删了),
|
|
103
|
+
// 只留两个改名按钮 —— 一个改主人称呼,一个改猪的名字。
|
|
104
|
+
if (ui.ownerEdit !== null || ui.pigNameEdit !== null) {
|
|
105
|
+
var forPig = ui.pigNameEdit !== null
|
|
106
|
+
var input = /** @type {HTMLInputElement} */ (el('input', 'dp-input'))
|
|
107
|
+
input.value = forPig ? ui.pigNameEdit : ui.ownerEdit
|
|
108
|
+
input.maxLength = 16
|
|
109
|
+
input.setAttribute(forPig ? 'data-pig-input' : 'data-owner-input', 'true')
|
|
110
|
+
input.addEventListener('input', function () {
|
|
111
|
+
if (forPig) ui.pigNameEdit = input.value
|
|
112
|
+
else ui.ownerEdit = input.value
|
|
113
|
+
})
|
|
114
|
+
var save = button('dp-mini', { 'data-name-save': forPig ? 'pig' : 'owner' }, function () {
|
|
115
|
+
var name = ((forPig ? ui.pigNameEdit : ui.ownerEdit) || '').trim()
|
|
116
|
+
if (forPig) ui.pigNameEdit = null
|
|
117
|
+
else ui.ownerEdit = null
|
|
118
|
+
if (name !== '') ui.send(forPig ? 'name' : 'owner', { name: name })
|
|
119
|
+
ui.renderContent()
|
|
120
|
+
})
|
|
121
|
+
save.textContent = '好'
|
|
122
|
+
var cancel = button('dp-mini dp-mini-plain', { 'data-name-cancel': 'true' }, function () {
|
|
123
|
+
ui.ownerEdit = null
|
|
124
|
+
ui.pigNameEdit = null
|
|
125
|
+
ui.renderContent()
|
|
126
|
+
})
|
|
127
|
+
cancel.textContent = '算了'
|
|
128
|
+
row.appendChild(input)
|
|
129
|
+
row.appendChild(save)
|
|
130
|
+
row.appendChild(cancel)
|
|
131
|
+
return row
|
|
132
|
+
}
|
|
133
|
+
var renameOwner = button('dp-mini dp-mini-plain', { 'data-owner-edit': 'true' }, function () {
|
|
134
|
+
ui.ownerEdit = ui.view.dialogue.ownerName
|
|
135
|
+
ui.renderContent()
|
|
136
|
+
})
|
|
137
|
+
renameOwner.textContent = '✏️ 称呼'
|
|
138
|
+
renameOwner.title = '现在叫「' + ui.view.dialogue.ownerName + '」'
|
|
139
|
+
var renamePig = button('dp-mini dp-mini-plain', { 'data-pig-edit': 'true' }, function () {
|
|
140
|
+
ui.pigNameEdit = ui.view.pig === null ? '' : ui.view.pig.name
|
|
141
|
+
ui.renderContent()
|
|
142
|
+
})
|
|
143
|
+
renamePig.textContent = '✏️ 名字'
|
|
144
|
+
renamePig.title = ui.view.pig === null ? '猪还没来' : '现在叫「' + ui.view.pig.name + '」'
|
|
145
|
+
var quiet = button('dp-mini dp-mini-plain', { 'data-quiet': ui.view.dialogue.quiet ? 'on' : 'off' }, function () {
|
|
146
|
+
ui.send('quiet', { on: !ui.view.dialogue.quiet })
|
|
147
|
+
})
|
|
148
|
+
quiet.textContent = ui.view.dialogue.quiet ? '🔕 免打扰中' : '🔔 免打扰'
|
|
149
|
+
row.appendChild(renameOwner)
|
|
150
|
+
row.appendChild(renamePig)
|
|
151
|
+
row.appendChild(quiet)
|
|
152
|
+
return row
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* The pig's banners — gone, sick, or out — at the top of the status tab only
|
|
157
|
+
* (B9: they used to sit above every tab, the shop included).
|
|
158
|
+
*/
|
|
159
|
+
function renderBanners(ui) {
|
|
160
|
+
if (ui.view.pig !== null && ui.view.dead) {
|
|
161
|
+
var dead = el('div', 'dp-alert dp-dead')
|
|
162
|
+
dead.appendChild(el('b', null, '🪦 ' + ui.view.pig.name + ' 走了' + (ui.view.pig.soul ? ',灵魂还留在墓碑上 👻' : '')))
|
|
163
|
+
dead.appendChild(el('div', null, ui.view.pig.soul
|
|
164
|
+
? '用还魂丹可以把它叫回来,也可以领养新的'
|
|
165
|
+
: '背包里的还魂丹就能救回来'))
|
|
166
|
+
ui.content.appendChild(dead)
|
|
167
|
+
// Adopting is available the moment the pig dies — not only once the
|
|
168
|
+
// soul turns up a day later. Waiting a day to start over was a
|
|
169
|
+
// mistake: the grave is already a dead end with nothing to do.
|
|
170
|
+
var adoptWrap = el('div', 'dp-actions')
|
|
171
|
+
var adopt = button('dp-btn dp-btn-wide', { 'data-action': 'adopt' }, function () { ui.send('adopt') })
|
|
172
|
+
adopt.appendChild(el('span', null, '📦'))
|
|
173
|
+
adopt.appendChild(el('span', null, '领养新猪'))
|
|
174
|
+
adoptWrap.appendChild(adopt)
|
|
175
|
+
ui.content.appendChild(adoptWrap)
|
|
176
|
+
} else if (ui.view.pig !== null && ui.view.pig.illness !== null) {
|
|
177
|
+
var illness = ui.view.pig.illness
|
|
178
|
+
var sick = el('div', 'dp-alert dp-sick')
|
|
179
|
+
sick.appendChild(el('b', null, '🤒 ' + illness.name + '(第 ' + illness.stage + '/4 期)'))
|
|
180
|
+
// B3: every stage has its own cure, and the wrong one makes it worse,
|
|
181
|
+
// so the alert always names the exact medicine.
|
|
182
|
+
sick.appendChild(el('div', null, '需要「' + illness.cureEmoji + illness.cure + '」—— 吃错药会加重'))
|
|
183
|
+
var needed = null
|
|
184
|
+
var shelf = ui.view.shop || []
|
|
185
|
+
for (var c = 0; c < shelf.length; c += 1) {
|
|
186
|
+
if (shelf[c].needed) needed = shelf[c]
|
|
187
|
+
}
|
|
188
|
+
// Hosts from before B3 do not flag the cure: match it by stage tier,
|
|
189
|
+
// then by name.
|
|
190
|
+
for (var t = 0; needed === null && t < shelf.length; t += 1) {
|
|
191
|
+
if (shelf[t].kind === 'medicine' && shelf[t].tier === illness.stage) needed = shelf[t]
|
|
192
|
+
}
|
|
193
|
+
for (var n = 0; needed === null && n < shelf.length; n += 1) {
|
|
194
|
+
if (shelf[n].label === illness.cure) needed = shelf[n]
|
|
195
|
+
}
|
|
196
|
+
if (ui.view.canGoOut) {
|
|
197
|
+
sick.appendChild(el('div', 'dp-dim', '带病出门报酬减半、病情更快'))
|
|
198
|
+
}
|
|
199
|
+
if (needed !== null && ui.view.canGoOut && ui.view.pig.coins < needed.price) {
|
|
200
|
+
sick.appendChild(el('div', 'dp-dim', '还差 ' + needed.price + ' 🪙 买「' + needed.label + '」,先去打工'))
|
|
201
|
+
}
|
|
202
|
+
ui.content.appendChild(sick)
|
|
203
|
+
if (illness.doctorFee !== null) {
|
|
204
|
+
var clinic = el('div', 'dp-actions')
|
|
205
|
+
var doctor = button('dp-btn dp-btn-wide', { 'data-action': 'doctor' }, function () { ui.send('doctor') })
|
|
206
|
+
doctor.appendChild(el('span', null, '🏥'))
|
|
207
|
+
doctor.appendChild(el('span', null, '看医生(' + illness.doctorFee + ' 🪙)'))
|
|
208
|
+
clinic.appendChild(doctor)
|
|
209
|
+
ui.content.appendChild(clinic)
|
|
210
|
+
}
|
|
211
|
+
} else if (ui.view.pig !== null && ui.view.activity !== null) {
|
|
212
|
+
var away = el('div', 'dp-alert dp-work')
|
|
213
|
+
away.appendChild(el('b', null, ui.view.activity.emoji + ' 在外面:' + ui.view.activity.label))
|
|
214
|
+
away.appendChild(el('div', null, '还有 ' + ui.view.activity.secondsLeft + ' 秒'))
|
|
215
|
+
ui.content.appendChild(away)
|
|
216
|
+
var wrap = el('div', 'dp-actions')
|
|
217
|
+
var call = button('dp-btn dp-btn-wide', { 'data-action': 'calloff' }, function () { ui.send('calloff') })
|
|
218
|
+
call.appendChild(el('span', null, '↩️'))
|
|
219
|
+
call.appendChild(el('span', null, '叫它回来'))
|
|
220
|
+
wrap.appendChild(call)
|
|
221
|
+
ui.content.appendChild(wrap)
|
|
222
|
+
}
|
|
223
|
+
}
|