Sync all projects

This commit is contained in:
github-actions[bot]
2026-07-16 18:15:59 +00:00
parent c0e8869625
commit 03689c0e84
13 changed files with 9588 additions and 13071 deletions
+1355 -4744
View File
@@ -1,4984 +1,1595 @@
```
<html><head><style>
/* --- Modern Theme Overrides --- */
:root {
--survival-primary: #111828;
--survival-secondary: rgba(32, 45, 68, 0.75);
--survival-surface: rgba(20, 34, 54, 0.78);
--survival-surface-strong: rgba(24, 36, 58, 0.92);
--survival-glass-border: rgba(148, 197, 255, 0.18);
--survival-accent: #5ea1ff;
--survival-accent-strong: #8fd6ff;
--survival-warning: #ffb86c;
--survival-success: #58f0a7;
--survival-danger: #ff7b9c;
--survival-text: #eff6ff;
--survival-muted: #a0aec0;
--survival-border: rgba(148, 197, 255, 0.25);
--survival-shadow: 0 24px 60px rgba(6, 12, 25, 0.55);
--survival-glow: 0 0 30px rgba(94, 161, 255, 0.35);
}
#
## AI
### 0
`<Analysis>` JSON Patch replace delta
### 1.
- `<status_current_variable>`
- `<ActionResult>` AI
- `<ActionResult>`
### 2. ActionResult
`<ActionResult>`
- (): ActionResult <>()(6)20調
- : "無"."無"
- "時間推進"
> 🔴 `//`
> - ActionResult : 06:0008:30 {"op": "replace", "path": "/系統/當前時間", "value": "08:30"}
- "無" `.` "無"
- ActionResult `//`
-
- `<weather_rules>` AI ActionResult
- ActionResult
- `<weather_rules>`
- `//` `//` 0
- Analysis {}
-
- 使
-
- ActionResult
- `replace` `//{}/`
- <>
- ActionResult"項目"//"項目進度更新"
- ActionResult"研究"//"研究進度更新"
-
- `{}`
- :[]
-
-
- / `.` `.`
- ()
-
| `:{}×{}REMOVERESET` | 1. insert <br>2. remove `//{}`<br>() |
-
| ActionResult | |
|------------------|------|
| `:{}({})×{}{N}` | 1. insert `//{}//{}`<br>2. replace `//{}/` = N |
| `:{}({}) ()` | |
- "無"
- ActionResult "無" Ai AI
- 使 ActionResult "無" AI
- > ActionResult > ActionResult
### 3.
> 🔴 `<sex_rules>` COT ActionResult
####
ActionResult
-
- true/false
- true/false
-
- ////
- /調//
-
-
-
####
ActionResult
= true
1.
{
"角色": ,
"完成": ,
"內射": ,
"授精者": ,
"避孕措施": ,
"情境": ,
"自願度": ,
"自願分級": ,
"描寫建議":
}
2. 使 `replace` `//`
3.
-
-
-
-
4. `//`
= false
-
-
- `//`
### 3.5
> 🔴 `<pregnancy_rules>` COT ActionResult
####
ActionResult
-
- /
-
-
- //
- ///
-
-
- /
- / +10 /
####
ActionResult =
1. ****
- `replace` `//{}//` "流產"
- `replace` `//{}//` 0
- `replace` `//{}//` 0
2. ****
- `replace` `//{}//` + 1
- `replace` `//{}//`
- `replace` `//{}//` 0
- `replace` `//{}//` true
3. **** ActionResult
- `delta` `//{}//` -[]
- `delta` `//{}//` -15
- `replace` `//{}//` "流產恢復期" "無"
4. **** ActionResult
- `delta` `//{}//` +[]
- 30`insert` `//{}//`
5. ****
- ActionResult =
- `insert` `//{}//-` "事件-流產-1-待觸發:流產後的情感與關係變化"
> 🔴 30 ×1.5 `<pregnancy_rules>` AI
body {
background: radial-gradient(circle at 20% 20%, rgba(94, 161, 255, 0.12), transparent 55%),
radial-gradient(circle at 80% 10%, rgba(255, 120, 180, 0.1), transparent 50%),
linear-gradient(160deg, #050a16, #101b2f 55%, #070b18);
font-family: "Inter", "Microsoft YaHei", "Segoe UI", Arial, sans-serif;
color: var(--survival-text);
min-height: 100vh;
margin: 0;
padding: 24px;
display: flex;
align-items: center;
justify-content: center;
background-attachment: fixed;
}
### 4.
.survival-ui {
width: clamp(320px, 92vw, 1180px);
margin: 0 auto;
padding: 18px clamp(18px, 3vw, 28px) 28px;
display: flex;
flex-direction: column;
gap: 28px;
border-radius: 28px;
background: var(--survival-surface);
border: 1px solid var(--survival-glass-border);
box-shadow: var(--survival-shadow);
backdrop-filter: blur(18px) saturate(160%);
position: relative;
overflow: hidden;
font-weight: 600;
font-family:"Microsoft YaHei","Segoe UI",Arial,sans-serif;color:var(--survival-text);gap:8px}
.survival-ui::before { /* */
content: "";
position: absolute;
inset: -60% 35% 45% -40%;
background: radial-gradient(circle, rgba(94, 161, 255, 0.16), transparent 60%);
opacity: 0.6;
pointer-events: none;
}
AIAI
.survival-ui::-webkit-scrollbar{width:6px}.survival-ui::-webkit-scrollbar-track{background:rgba(0,0,0,.2);border-radius:3px}.survival-ui::-webkit-scrollbar-thumb{background:var(--survival-accent);border-radius:3px}
.section__title {
font-size: 15px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--survival-muted);
margin: 0 0 12px;
}
---
### 🔴 (ReadOnly Master Path Index)
AI JSON Patch 使
{
"睡眠": "/精神/睡眠",
"壓力": "/精神/壓力",
"性慾": "/精神/性慾",
"無聊": "/精神/無聊",
"孤獨": "/精神/孤獨",
"疲勞": "/狀態/疲勞",
"清潔": "/狀態/清潔",
"疼痛": "/狀態/疼痛",
"當前生命值": "/生理/當前生命值",
"體溫": "/生理/體溫",
"水分": "/生理/水分",
"飽腹感": "/生理/飽腹感",
"排泄欲": "/生理/排泄欲",
"碳水": "/生理/碳水",
"脂肪": "/生理/脂肪",
"氮平衡": "/生理/氮平衡",
"蛋白質": "/生理/蛋白質",
"維生素": "/生理/維生素",
"免疫負荷": "/生理/免疫負荷",
"當前存糧": "/系統/當前存糧天數"
.section__list{list-style:none;margin:0;padding-left:12px;font-size:14px;line-height:1.35}
.item{display:flex;justify-content:space-between;gap:4px}
.item__key{white-space:nowrap}
.item__value{font-weight:600}
/* --- - --- */
/* 1. - 14 */
.survival-ui .inventory-grid.equipment-grid {
display: grid !important;
grid-template-columns: repeat(4, 1fr) !important; /* 4 */
grid-template-rows: repeat(2, auto) !important; /* */
gap: 15px !important;
margin-top: 20px !important;
margin-bottom: 20px !important;
}
/* 2. */
.survival-ui .equipment-slot {
background: var(--survival-surface-strong) !important;
border: 1px solid var(--survival-glass-border) !important;
border-radius: 12px !important;
padding: 16px !important;
transition: all 0.3s ease !important;
min-height: 140px !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: flex-start !important;
text-align: center !important;
position: relative !important;
overflow: hidden !important;
}
* `//{}` //////*
/* 3. */
.survival-ui .equipment-slot:hover {
transform: translateY(-3px) !important;
box-shadow:
0 8px 25px rgba(0, 0, 0, 0.3),
0 0 20px rgba(94, 161, 255, 0.15) !important;
background: rgba(40, 55, 85, 0.9) !important;
border-color: var(--survival-accent) !important;
}
#### 🔴
/* 4. - 20px */
.survival-ui .equipment-slot .slot-title {
color: #d17d2e !important;
font-weight: 700 !important;
font-size: 20px !important;
text-shadow: none !important;
letter-spacing: 0.05em !important;
text-transform: uppercase !important;
margin-bottom: 12px !important;
padding-bottom: 8px !important;
border-bottom: 1px solid rgba(148, 197, 255, 0.2) !important;
line-height: 1.2 !important;
width: 100% !important;
text-align: center !important;
}
| | | | | |
|------|----------|----------|----------|------------|
| | `//{}` | | `//{}//{}` | |
| | `//{}` | | `//{}//{}` | |
| | `//{}` | | `//{}//{}` | |
| | `//{}` | | `//{}//{}` | |
| | `//{}` | | `//{}//{}` | |
| | `//{}` | | `//{}//{}` | |
/* 5. - 16px */
.survival-ui .equipment-slot .equipment-item-name {
font-size: 16px !important;
font-weight: 600 !important;
color: var(--survival-accent-strong) !important;
margin-bottom: 10px !important;
padding: 8px 10px !important;
background: rgba(94, 161, 255, 0.1) !important;
border: 1px solid rgba(94, 161, 255, 0.2) !important;
border-radius: 6px !important;
width: 100% !important;
text-align: center !important;
word-wrap: break-word !important;
}
1. `//`
2.
/* 6. - 20px */
.survival-ui .equipment-slot .equipment-empty {
display: flex !important;
align-items: center !important;
justify-content: center !important;
height: 100% !important;
min-height: 80px !important;
font-size: 20px !important;
font-weight: 600 !important;
color: var(--survival-muted) !important;
width: 100% !important;
text-align: center !important;
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
}
---
/* 7. */
.survival-ui .equipment-slot .equipment-item-props {
font-size: 12px !important;
color: var(--survival-text) !important;
text-align: left !important;
line-height: 1.4 !important;
margin-top: 10px !important;
padding: 8px !important;
background: rgba(20, 30, 50, 0.5) !important;
border-radius: 6px !important;
border: 1px solid rgba(94, 161, 255, 0.1) !important;
width: 100% !important;
}
#### 🔴
/* 8. */
.survival-ui .equipment-slot .equipment-prop {
display: flex !important;
align-items: flex-start !important;
margin-bottom: 4px !important;
font-size: 12px !important;
line-height: 1.4 !important;
}
| | | |
|------|----------|------------------|
| | `//` | `//``//` |
| | `//{}//` | `//``//{}//` |
.survival-ui .equipment-slot .equipment-prop .prop-key {
color: var(--survival-muted) !important;
white-space: nowrap !important;
flex-shrink: 0 !important;
min-width: 50px !important;
font-size: 12px !important;
}
- Object
- AI
.survival-ui .equipment-slot .equipment-prop .prop-sep {
flex-shrink: 0 !important;
white-space: nowrap !important;
margin-right: 4px !important;
font-size: 12px !important;
}
---
.survival-ui .equipment-slot .equipment-prop .prop-val {
word-break: break-word !important;
min-width: 0 !important;
font-weight: 500 !important;
font-size: 12px !important;
color: var(--survival-text) !important;
line-height: 1.4 !important;
}
####
/* 9. */
@media (max-width: 1024px) {
.survival-ui .inventory-grid.equipment-grid {
grid-template-columns: repeat(2, 1fr) !important; /* 2 */
}
}
#####
- //////
-
- AI/
- 0
-
- AI
-
- >70 +5
@media (max-width: 768px) {
.survival-ui .inventory-grid.equipment-grid {
grid-template-columns: 1fr !important; /* */
gap: 12px !important;
}
}
#####
- ////
-
- AI
- `<sex_rules>`
/* 10. 102 */
/* */
.survival-ui .equipment-slot[data-slot="頭部"] { order: 1; }
.survival-ui .equipment-slot[data-slot="頸部"] { order: 2; }
.survival-ui .equipment-slot[data-slot="胸部"] { order: 3; }
.survival-ui .equipment-slot[data-slot="背部"] { order: 4; }
.survival-ui .equipment-slot[data-slot="腰部"] { order: 5; }
/* */
.survival-ui .equipment-slot[data-slot="左手"] { order: 6; }
.survival-ui .equipment-slot[data-slot="右手"] { order: 7; }
.survival-ui .equipment-slot[data-slot="腿部"] { order: 8; }
.survival-ui .equipment-slot[data-slot="腳部"] { order: 9; }
.survival-ui .equipment-slot[data-slot="其他"] { order: 10; }
/* --- --- */
.companion-equipment-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 10px;
margin-top: 15px;
}
#####
- ////////
- AI
-
- AI
.companion-equipment-slot {
background: rgba(30, 45, 70, 0.7);
border: 1px solid rgba(148, 197, 255, 0.2);
border-radius: 8px;
padding: 12px;
transition: all 0.2s ease;
min-height: 100px;
}
---
.companion-equipment-slot:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
border-color: var(--survival-accent);
}
####
.companion-equipment-slot .slot-title {
font-size: 14px;
font-weight: 600;
color: #ffb86c;
margin-bottom: 8px;
text-transform: uppercase;
}
.companion-equipment-slot .item-name {
font-size: 15px;
font-weight: 600;
color: var(--survival-accent-strong);
margin-bottom: 8px;
}
🔴
/* --- v5.0 · · By --- */
/* */
.camp-info-item {
font-size: 16px !important;
font-weight: 700 !important;
padding: 0; /* */
line-height: 1.6;
transition: all 0.2s ease;
/* margin-bottom */
margin-bottom: 0 !important;
}
#####
- //
-
- AI便
- -2/
/* */
.camp-info-container {
display: flex; /* flex*/
flex-direction: column; /* */
gap: 8px; /* 8px*/
margin-bottom: 28px; /* 24px */
/* paddingmargin-top */
}
#####
- /
-
- AI
#####
- /
-
- AI
- +10 +20
- -2 -1>60
/* */
.camp-info-item .prop-key,
.camp-info-item .prop-sep {
color: #ffb86c !important;
}
#####
- `//{}//`
- AI
- AI
.camp-info-item .prop-val {
color: var(--survival-text) !important;
}
---
.camp-info-item:hover .prop-key,
.camp-info-item:hover .prop-sep {
color: #ffd19a !important;
text-shadow: 0 0 8px rgba(255, 184, 108, 0.6);
}
####
.camp-info-item:hover .prop-val {
color: #ffffff !important;
}
#####
- -12.5
- -1.5
.top-info {
display: grid;
grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) minmax(0, 2fr);
gap: 18px;
padding: 22px clamp(18px, 3vw, 24px);
border-radius: 22px;
background: var(--survival-surface-strong);
border: 1px solid var(--survival-glass-border);
box-shadow: var(--survival-glow);
align-items: center;
}
#####
- 8. -2
@media (max-width: 960px) {
.top-info {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.top-info .location-display {
grid-column: 1 / -1;
}
}
### 5.
@media (max-width: 720px) {
.top-info {
grid-template-columns: 1fr;
align-items: flex-start;
}
}
.top-info .time-display {
font-size: clamp(44px, 7vw, 66px);
font-weight: 700;
line-height: 1;
letter-spacing: -0.04em;
color: var(--survival-accent-strong);
text-shadow: 0 0 32px rgba(94, 161, 255, 0.45);
}
. 00:00 <
-
- `.` `{}`
- `. ` `. `
- <>
.top-info .info-stack {
display: grid;
gap: 12px;
}
🔴
-
-
-
-
-
- 🔴 `<weather_rules>` COT ActionResult
- 🔴
- `` -5 0
- ` 50` `<pregnancy_rules>`
### 6.
.top-info .info-row {
display: flex;
flex-wrap: wrap;
gap: 12px 18px;
color: var(--survival-text); /* High contrast */
font-size: 15px;
margin-bottom: 4px; /* */
}
.row-item { white-space: nowrap; }
🔴
| | |
|------|------|
| | `.<>.` |
| | `..<>.` |
| | `.<>.` |
| | `.<>.` |
| | `.<>.` |
.top-info .info-row .row-item:nth-child(3) {
color: #8fd6ff; /* */
font-weight: 600;
}
### 7.
.top-info .location-display {
justify-self: end;
font-size: clamp(20px, 3.2vw, 30px);
font-weight: 600;
color: var(--survival-text);
}
@media (max-width: 720px) {
.top-info .location-display {
justify-self: start;
margin-top: 8px;
width: 100%;
font-size: 24px;
}
}
> 🔴 **** delta `//{}/{}/{}`
.core-stats-wrapper{display:flex;gap:12px;margin-top:10px}.core-stats-wrapper .core-stat-item{flex:1}
.progress-wrapper{margin-bottom:16px}
.mini-progress-wrapper{display:flex;align-items:center;gap:8px;flex:1;min-width:0}
.mini-progress-wrapper .mini-progress__text{font-size:12px;white-space:nowrap;min-width:40px;text-align:right}
ActionResult
@media(max-width: 480px){.mini-progress-wrapper{flex:1;width:100%}}
#### /
/* --- v4.0 - --- */
.collapsible {
margin-bottom: 24px;
border: 1px solid var(--survival-border);
border-radius: 6px;
overflow: hidden;
}
.collapsible__header {
/* flex */
display: flex;
justify-content: space-between;
align-items: center;
background: rgba(40, 58, 88, 0.85); /* 2. */
padding: 16px 20px; /* 3. */
font-size: 16px; /* */
color: #FFFFFF;/* 4. 使 */
font-weight: 700; /* */
border-left: 5px solid var(--survival-accent); /* */
transition: background 0.3s ease; /* */
cursor: pointer;
}
- `.`ActionResult
- `.`+10+20
- `.`
- `.` >
- `.`ActionResult/
/* */
.collapsible__header:hover {
background: rgba(55, 78, 115, 0.95);
}
#### /
/* 2. .collapsible */
.collapsible {
border-radius: 14px; /* 5. 6px 14px */
border: 1px solid var(--survival-glass-border); /* */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); /* */
margin-bottom: 16px; /* */
}
- `.`100
- `.////`
- `.`
- 200075%
- `.`+5+10
- `.`
- `.`
- `.`
- . `//`
- `//`
-
/* 3. */
.collapsible__body {
background: rgba(10, 20, 35, 0.6); /* */
padding: 20px; /* */
border-top: 1px solid var(--survival-glass-border); /* */
display: none; /* */
}
####
.collapsible__bars-container{display:flex;flex-wrap:wrap;gap:8px;flex:1;min-width:0}
@media(max-width: 480px){.collapsible__bars-container{flex-direction:column;width:100%}}
.collapsible.active .collapsible__header:after{transform:rotate(0)}
.collapsible.active .collapsible__header--with-progress .collapsible__indicator{transform:rotate(0)}
.temp-range-wrapper { margin:10px 0 15px; padding:10px; background:rgba(0,0,0,.15); border-radius:6px; font-size:14px; }
.nutrition-hydration-wrapper { display:flex; flex-direction:column; gap:10px; background:rgba(0,0,0,.15); padding:10px; border-radius:4px; }
.phys-mental-wrapper { display:flex;gap:32px;flex-wrap:wrap; }
.phys-mental-wrapper .phys-col,
.phys-mental-wrapper .mental-col { flex:1 1 300px; min-width:260px; background:rgba(0,0,0,.15); padding:10px; border-radius:4px; }
.attr-skill-wrapper .attr-col,
.attr-skill-wrapper .skill-col { flex:1 1 300px; min-width:260px; background:rgba(0,0,0,.15); padding:10px; border-radius:4px; }
.task-bar { margin-bottom:12px; background:var(--survival-surface-strong); border:1px solid var(--survival-glass-border); border-radius:20px; padding:18px clamp(18px, 3vw, 24px); }
/* --- CSS --- */
.status-effects-container {
margin-top: 12px; /* */
margin-bottom: 4px; /* */
padding: 10px;
background: rgba(0,0,0,.15);
border-radius: 6px;
}
.status-effects-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
}
.status-effect-container {
display: flex;
flex-direction: column;
}
.status-effect-name {
padding: 4px 10px;
background: var(--survival-bg-light);
border: 1px solid var(--survival-border);
border-radius: 4px;
font-size: 13px;
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
white-space: nowrap; /* */
transition: all 0.2s ease;
cursor: default;
min-height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
- `.` 0
- `.` -10
/* - */
.status-effect-name.has-effect {
cursor: pointer;
position: relative;
padding-right: 20px; /* */
}
- `.` 0
- `.`-30
- `.`+20
-
/* - */
.status-effect-name.has-effect::after {
content: '';
font-size: 10px;
margin-left: 5px;
transition: transform 0.3s ease;
position: absolute;
right: 8px;
}
#### /
/* */
.status-effect-name.has-effect.expanded::after {
transform: rotate(180deg);
}
> 🔴 / `<crafting_rules>` COT ActionResult
.status-effect-name:hover {
transform: translateY(-2px);
background: var(--survival-secondary);
border-color: var(--survival-accent);
}
-
-
- ( / 100) ×
- remove
-
-
-
- < 100% =
- = 100%
-
- ActionResult
- remove insert
-
- `.`
- `.`
/* */
.status-effect-detail {
background: rgba(0, 0, 0, 0.25);
border: 1px solid var(--survival-border);
border-radius: 4px;
padding: 8px 10px;
margin-top: 4px;
font-size: 12px;
line-height: 1.4;
color: var(--survival-text);
white-space: normal; /* */
max-width: 250px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
animation: fadeIn 0.2s ease;
}
#### /
/* */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-5px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
- `.`
- `.`
- `.`
- `.`
- `.`
- `.`
- //
-
- `.`
/* */
@media (max-width: 768px) {
.status-effects-list {
gap: 6px;
}
.status-effect-name {
padding: 4px 8px;
font-size: 12px;
}
.status-effect-detail {
max-width: 200px;
font-size: 11px;
padding: 6px 8px;
}
.status-effect-name.has-effect {
padding-right: 25px; /* */
}
.status-effect-name.has-effect::after {
right: 6px;
font-size: 11px;
}
}
#### /
/* */
@media (max-width: 480px) {
.status-effects-container {
padding: 8px;
}
.status-effects-list {
justify-content: center;
}
.status-effect-detail {
max-width: 180px;
}
}
/* --- CSS --- */
/* */
.bonus-prop {
background: rgba(94, 161, 255, 0.08) !important;
border-left: 3px solid var(--survival-accent) !important;
padding: 6px 8px 6px 10px !important;
border-radius: 4px !important;
margin: 4px 0 !important;
}
- `.`6-8
- `.`
- `.`
- `.`>60
- `.`
- `.`使
- `..`
.bonus-prop .prop-key {
color: var(--survival-accent-strong) !important;
font-weight: 700 !important;
}
#### /
.bonus-prop .prop-val {
color: #8fd6ff !important;
font-weight: 600 !important;
}
/* */
.bonus-separator {
animation: separatorGlow 3s ease-in-out infinite;
}
-
- +25+50+75
@keyframes separatorGlow {
0%, 100% {
background: linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent);
}
50% {
background: linear-gradient(90deg, transparent, rgba(94, 161, 255, 0.6), transparent);
}
}
- 使
- +25+50+75
/* */
.talent-bonus-line {
background: rgba(94, 161, 255, 0.08) !important;
border-left: 3px solid var(--survival-accent) !important;
padding: 6px 8px 6px 10px !important;
border-radius: 4px !important;
margin: 8px 0 !important;
color: #8fd6ff !important;
font-weight: 600 !important;
}
/* */
.talent-has-bonus .skill-name::after {
content: "✨";
margin-left: 8px;
font-size: 12px;
color: var(--survival-accent);
animation: sparkle 2s ease-in-out infinite;
}
/使
@keyframes sparkle {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
####
.temp-range-bar,
.nitrogen-gradient,
.immune-bar,
.progress,
.mini-progress {
height: 12px;
background: linear-gradient(135deg, rgba(18, 30, 48, 0.65), rgba(11, 20, 31, 0.65));
border-radius: 999px;
border: 1px solid rgba(148, 197, 255, 0.14);
position: relative;
overflow: visible;
}
/* --- --- */
/* */
.temp-range-bar .temp-gradient {
/* */
background-image: linear-gradient(90deg, #3498db 0%, #2ecc71 50%, #e74c3c 100%) !important;
width: 100%; /* 滿 */
position: absolute;
top: 0;
left: 0;
height: 100%;
border-radius: inherit;
}
-
-
.mini-progress { height: 8px; }
.progress__bar,
.mini-progress__bar,
.immune-fill,
.temp-gradient {
position:absolute; top:0; left:0; height:100%;
border-radius: inherit;
background-image: linear-gradient(90deg, rgba(94, 161, 255, 0.9), rgba(96, 225, 183, 0.9));
box-shadow: 0 0 18px rgba(94, 161, 255, 0.35);
}
.hp-progress .progress__bar { background-image: linear-gradient(90deg, #ff8fb1, #58f0a7); }
.mp-progress .progress__bar { background-image: linear-gradient(90deg, #8c8bff, #58f0a7); }
.hunger-progress .progress__bar, .hunger-progress.mini-progress .mini-progress__bar { background-image: linear-gradient(90deg, #ffdc84, #ff9f6c); }
.water-progress .progress__bar, .water-progress.mini-progress .mini-progress__bar { background-image: linear-gradient(90deg, #7fd8ff, #5ea1ff); }
1.
2. 使 delta
3. 使 insert
.carbs-progress .progress__bar{background-image:linear-gradient(90deg, #f39c12, #d35400)}
.fat-progress .progress__bar{background-image:linear-gradient(90deg, #f1c40f, #f39c12)}
.protein-progress .progress__bar{background-image:linear-gradient(90deg, #27ae60, #16a085)}
.vitamin-progress .progress__bar{background-image:linear-gradient(90deg, #2ecc71, #27ae60)}
#### 🔴
.progress-wrapper > div:first-child, .mini-progress__text, .progress-number {
/* --- --- */
font-family: "IBM Plex Mono", Consolas, monospace;
}
.mini-progress__text {
font-family: "IBM Plex Mono", Consolas, monospace;
font-size: 13px;
letter-spacing: 0.06em;
color: var(--survival-text); /* High Contrast */
}
.button-container{
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: flex-end;
margin-top:auto;
}
| | | |
|--------|----------|------|
| | `//{}` | `//` |
| | `//{}//{}` | `////` |
@media (max-width: 600px) {
.button-container {
justify-content: stretch;
}
****
1. 使
2. 使 使 `//{}`
3. 使 使 `//{}//{}`
4. 使
.action-btn { /* Renamed for clarity */
flex: 1 1 100%;
text-align: center;
}
}
**🔴 **
- 使 `//`
- 使 `//{}//`
- XX
.action-btn { /* Renamed and unified */
position: relative;
padding: 12px 18px;
border-radius: 999px;
border: 1px solid rgba(148, 197, 255, 0.25);
background: linear-gradient(135deg, rgba(17, 31, 49, 0.9), rgba(29, 45, 68, 0.85));
color: var(--survival-text);
font-family: "Inter", "Microsoft YaHei", sans-serif;
font-size: 14px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
overflow: hidden;
cursor: pointer;
transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
### 8.
.action-btn::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(120deg, transparent 25%, rgba(94, 161, 255, 0.2), transparent 75%);
opacity: 0;
transition: opacity 0.3s ease;
}
#### 8.1
.action-btn:hover {
transform: translateY(-3px);
border-color: rgba(148, 197, 255, 0.55);
box-shadow: 0 12px 28px rgba(8, 18, 34, 0.35);
}
#####
.action-btn:hover::before {
opacity: 1;
}
- `.` `{}`
-
- +
.action-btn:active {transform:translateY(0)}
#####
/* Breathing light effect for draw buttons */
.draw-btn.survival {
animation: glow-survival 3s ease-in-out infinite;
}
- `.` `{}`
-
- +
@keyframes glow-survival {
0%, 100% {
box-shadow: 0 0 5px rgba(94, 161, 255, 0.2), 0 0 10px rgba(94, 161, 255, 0.2);
border-color: rgba(94, 161, 255, 0.4);
}
50% {
box-shadow: 0 0 15px rgba(94, 161, 255, 0.5), 0 0 25px rgba(94, 161, 255, 0.5);
border-color: rgba(148, 197, 255, 0.8);
}
}
#####
@keyframes glow-miracle {
0%, 100% {
box-shadow: 0 0 5px rgba(243, 156, 18, 0.2), 0 0 10px rgba(243, 156, 18, 0.2);
border-color: rgba(243, 156, 18, 0.4);
}
50% {
box-shadow: 0 0 15px rgba(243, 156, 18, 0.5), 0 0 25px rgba(243, 156, 18, 0.5);
border-color: rgba(255, 184, 108, 0.8);
}
}
- 00:00 `.` `{}`
-
-
-
.inventory-modal{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.8);backdrop-filter:blur(8px);z-index:1000;display:flex;justify-content:center;align-items:center}
/* --- --- */
.inventory-modal__content {
position: relative;
/* 90%1400px滿 */
width: clamp(90%, 95vw, 1400px);
height: clamp(80%, 90vh, 800px); /* */
padding: 20px;
overflow-y:auto;display:flex;flex-direction:row;gap:20px;
border-radius: 26px;
border: 1px solid rgba(148, 197, 255, 0.18);
background: linear-gradient(155deg, rgba(17, 28, 45, 0.94), rgba(24, 36, 58, 0.94));
box-shadow: var(--survival-shadow);
backdrop-filter: blur(20px) saturate(160%);
animation:modalFadeIn .3s ease-out
}
#####
.inventory-modal__close{position:absolute;top:10px;right:15px;font-size:24px;cursor:pointer;color:var(--survival-text);transition:all .2s ease;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:50%;background: rgba(0,0,0,0.6)}
.inventory-modal__close:hover{color:var(--survival-danger);background:rgba(231,76,60,.2);transform:scale(1.1)}
@keyframes modalFadeIn{from{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}
.attr-skill-wrapper{display:flex;gap:24px;flex-wrap:wrap}
.attr-skill-wrapper .attr-col,.attr-skill-wrapper .skill-col{flex:1 1 300px;min-width:260px;background:rgba(0,0,0,.15);padding:18px;border-radius:16px;}
.inventory-grid {
display: grid;
/* 320px
3-4 */
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 6px; /* */
}
.inventory-item {
background: var(--survival-surface-strong);
border: 1px solid var(--survival-border);
border-radius: 10px; /* */
padding: 16px; /* */
transition: all .25s ease-out;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
align-items: flex-start;
text-align: left;
min-height: 100px; /* */
box-shadow: var(--survival-glow); /* */
}
.inventory-item:hover{transform:translateY(-3px);box-shadow:0 5px 15px rgba(0,0,0,.3);background:rgba(52,73,94,.9);border-color:var(--survival-accent)}
.inventory-item .item-name {
font-weight: 600; /* */
margin-bottom: 12px;
font-size: 18px; /* 16px -> 18px */
color: var(--survival-accent-strong); /* 使調 */
letter-spacing: 0.05em; /* */
}
/* --- --- */
.inventory-list {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 */
gap: 12px; /* */
margin-top: 10px;
margin-bottom: 20px;
}
- `.` `{}`
-
-
-
-
-
- +
/* 調 */
.inventory-list-item {
background: var(--survival-surface-strong);
border: 1px solid var(--survival-border);
border-radius: 10px;
padding: 16px;
transition: all .25s ease-out;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
align-items: flex-start;
text-align: left;
min-height: 120px; /* */
box-shadow: var(--survival-glow);
}
#####
.inventory-list-item:hover {
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0,0,0,.3);
background: rgba(52,73,94,.9);
border-color: var(--survival-accent);
}
- `.` `{}` /
.inventory-list-item .item-name {
font-weight: 600;
margin-bottom: 12px;
font-size: 18px;
color: var(--survival-accent-strong);
letter-spacing: 0.05em;
}
滿
/* */
@media (max-width: 960px) {
.inventory-list {
grid-template-columns: repeat(2, 1fr); /* 2 */
}
}
1. -
- /
-
@media (max-width: 640px) {
.inventory-list {
grid-template-columns: 1fr; /* 1 */
}
}
/* --- v5.0 - --- */
/* */
.item-prop {
display: flex; /* Flexbox */
align-items: flex-start; /* */
gap: 4px; /* */
font-size: 14px;
line-height: 1.6;
color: #ffffff;
}
2.
- /
- /
/* - */
/* 調 */
.item-prop .prop-key {
color: var(--survival-muted);
white-space: nowrap; /* <-- */
3.
- //
- /
}
.item-prop .prop-sep {
flex-shrink: 0; /* */
white-space: nowrap; /* */
}
.item-prop .prop-sep {
white-space: nowrap; /* <-- */
flex-shrink: 0; /* <-- flex */
}
-
- /
-
-
-
-
/* - */
.item-prop .prop-val {
/* flex */
word-break: break-word; /* */
min-width: 0; /* */
font-weight: 500;
}
.inventory-list-item{background:var(--survival-bg-light);border:1px solid var(--survival-border);border-radius:6px;padding:12px;transition:all .2s ease-out;display:flex;flex-direction:column;position:relative;overflow:hidden}
.inventory-list-item:hover{transform:translateY(-2px);box-shadow:0 3px 10px rgba(0,0,0,.3);background:rgba(52,73,94,.9);border-color:var(--survival-accent)}
.inventory-list-item .item-name{font-weight:bold;margin-bottom:6px;font-size:16px;color:#fff}
/*.nitrogen-balance:before{content:"";position:absolute;top:0;bottom:0;left:50%;width:2px;background:hsla(0,0%,100%,.7);z-index:1}*/
.vertical-progress{width:30px;height:200px;background:rgba(0,0,0,.3);border-radius:15px;position:relative;margin:20px auto;box-shadow:inset 0 0 10px rgba(0,0,0,.5)}
.vertical-progress__bar{position:absolute;bottom:0;left:0;width:100%;background:linear-gradient(to top, var(--survival-warning), var(--survival-accent));border-radius:15px;transition:height .5s ease-out;box-shadow:0 0 10px rgba(52,152,219,.5)}
.vertical-progress__label{position:absolute;bottom:-30px;left:50%;transform:translateX(-50%);white-space:nowrap;text-align:center;width:100px;font-weight:bold;color:var(--survival-text);text-shadow:0 1px 2px rgba(0,0,0,.5)}
.vertical-progress__value{position:absolute;top:-30px;left:50%;transform:translateX(-50%);white-space:nowrap;text-align:center;width:100px;font-weight:bold;color:var(--survival-accent);text-shadow:0 1px 2px rgba(0,0,0,.5)}
.weight-container{display:flex;flex-direction:column;align-items:center;min-width:100px;padding-right:20px;border-right:1px solid var(--survival-border);justify-content:center}
.inventory-content{flex:1;display:flex;flex-direction:column;overflow-y:auto}
.inventory-content h3{margin-top:0;margin-bottom:15px;color:var(--survival-accent);font-size:18px;border-bottom:1px solid hsla(0,0%,100%,.1);padding-bottom:8px;position:relative}
.inventory-content h3:after{content:"";position:absolute;bottom:-1px;left:0;width:60px;height:2px;background:var(--survival-accent)}
.temp-range-wrapper{font-size:14px}
.temp-range-bar{height:16px;margin-top:8px;overflow:visible}
.comfort-zone{position:absolute;height:100%;background:hsla(0,0%,100%,.2);border:1px dashed hsla(0,0%,100%,.7);border-radius:8px;z-index:1}
.current-temp{position:absolute;width:4px;height:24px;background:#fff;border-radius:2px;top:-4px;transform:translateX(-2px);z-index:2;box-shadow:0 0 5px hsla(0,0%,100%,.8)}
.nitrogen-gradient{height:12px;}
.nitrogen-marker{position:absolute;top:-6px;bottom:-6px;width:4px;background:#fff;border-radius:2px;box-shadow:0 0 5px hsla(0,0%,100%,.8)}
.temp-gradient{height:12px; background-image: linear-gradient(90deg, #3498db 0%, #2ecc71 50%, #e74c3c 100%);}
.temp-marker{position:absolute;top:-6px;bottom:-6px;width:4px;background:#fff;border-radius:2px;box-shadow:0 0 5px hsla(0,0%,100%,.8)}
.temp-normal-zone{position:absolute;height:100%;background:hsla(0,0%,100%,.2);border:1px dashed hsla(0,0%,100%,.7);border-radius:4px;z-index:1}
.temp-gradient{height:12px; background-image: linear-gradient(90deg, #3498db 0%, #2ecc71 50%, #e74c3c 100%);}
.temp-marker{position:absolute;top:-6px;bottom:-6px;width:4px;background:#fff;border-radius:2px;box-shadow:0 0 5px hsla(0,0%,100%,.8)}
.temp-normal-zone{position:absolute;height:100%;background:hsla(0,0%,100%,.2);border:1px dashed hsla(0,0%,100%,.7);border-radius:4px;z-index:1}
.immune-bar{height:12px;}
.immune-fill{background-image:linear-gradient(90deg, #2ecc71 0%, #f39c12 50%, #e74c3c 100%);transition:width .3s ease}
.immune-marker{position:absolute;top:-6px;bottom:-6px;width:4px;background:#fff;border-radius:2px;box-shadow:0 0 5px hsla(0,0%,100%,.8);z-index:2}
.skill-item{margin-bottom:2px;background:rgba(0,0,0,.1);padding:2px 8px;border-radius:4px}
.skill-item .skill-name{font-weight:bold;margin-bottom:5px}
.skill-desc { font-size: .85em; color: var(--survival-muted); opacity: 0.8; margin-top: 4px; }
/* - */
.task-strip.world-task {
background: linear-gradient(135deg,
rgba(255, 215, 0, 0.25),
rgba(255, 165, 0, 0.15),
rgba(255, 215, 0, 0.08));
border-color: rgba(255, 215, 0, 0.6);
color: #ffd966;
text-shadow: 0 0 8px rgba(255, 215, 0, 0.5);
border-width: 2px;
box-shadow: 0 0 15px rgba(255, 215, 0, 0.3);
animation: worldTaskGlow 3s ease-in-out infinite;
}
+ /// 2~4
.task-strip.world-task:hover {
transform: translateY(-2px);
box-shadow: 0 0 25px rgba(255, 215, 0, 0.5);
border-color: rgba(255, 215, 0, 0.9);
}
#####
/* */
@keyframes worldTaskGlow {
0%, 100% {
box-shadow: 0 0 8px rgba(255, 215, 0, 0.3);
border-color: rgba(255, 215, 0, 0.5);
}
50% {
box-shadow: 0 0 20px rgba(255, 215, 0, 0.6);
border-color: rgba(255, 215, 0, 0.9);
}
}
- `{}` `[]` 滿
-
-
-
-
-
-
-
- +
/* */
.task-detail.world-detail {
background: linear-gradient(135deg,
rgba(255, 215, 0, 0.08),
rgba(0, 0, 0, 0.3));
border: 1px solid rgba(255, 215, 0, 0.3);
}
/* */
.task-strip {
padding: 12px 16px;
margin: 8px 0;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
text-align: center;
border: 1px solid transparent;
}
#### 8.2
.task-strip:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
- 1
- 1
.task-strip.main-task {
background: linear-gradient(135deg, rgba(52, 152, 219, 0.2), rgba(52, 152, 219, 0.1));
border-color: rgba(52, 152, 219, 0.3);
color: #3498db;
}
.task-strip.side-task {
background: linear-gradient(135deg, rgba(243, 156, 18, 0.2), rgba(243, 156, 18, 0.1));
border-color: rgba(243, 156, 18, 0.3);
color: #f39c12;
}
#### 8.3
.task-strip.emergency-task {
background: linear-gradient(135deg, rgba(231, 76, 60, 0.2), rgba(231, 76, 60, 0.1));
border-color: rgba(231, 76, 60, 0.3);
color: #e74c3c;
animation: pulse 2s infinite;
}
/* */
.task-strip.daily-task {
background: linear-gradient(135deg, rgba(46, 204, 113, 0.2), rgba(46, 204, 113, 0.1));
border-color: rgba(46, 204, 113, 0.3);
color: #2ecc71;
}
- 1 ~ 3
- 1 ~ 2
/* */
.task-strip.bond-task {
background: linear-gradient(135deg, rgba(189, 147, 249, 0.25), rgba(189, 147, 249, 0.15)); /* 調 */
border-color: rgba(142, 68, 173, 0.4); /* */
color: #f0e6ff; /* */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); /* */
}
- 0
- 0 1
.task-detail {
background: rgba(0, 0, 0, 0.15);
border-radius: 8px;
padding: 16px;
margin: 8px 0;
border: 1px solid rgba(255, 255, 255, 0.1);
}
- 60%
- 40%
-
.task-desc {
text-align: left;
margin-bottom: 16px;
line-height: 1.4;
color: var(--survival-text);
white-space: pre-line;
word-wrap: break-word;
/* */
font-size: 15px; /* */
}
- 7-30
- 3-7
- 1-3
- 0
-
- 3-5
.target-section {
margin: 16px 0;
}
.section-title {
font-weight: 600;
margin-bottom: 8px;
color: var(--survival-accent);
/* */
font-size: 15px; /* "任務要求""進階目標" */
}
#### 8.4
.target-desc {
margin-bottom: 8px;
line-height: 1.4;
color: var(--survival-text);
white-space: pre-line;
word-wrap: break-word;
/* */
font-size: 15px; /* */
}
.reward-info {
color: var(--survival-text);
font-weight: 600;
margin-top: 13px;
/* */
font-size: 15px; /* */
}
- `////{N}`
- `////{N}`
- `////{N}`
- `////{N}`
- `////1`
- `////{N}`
- `////{N}`
- `////{N}`
- `////{N}`
- `///{}//{N}`
- `///{}//{N}`
.reward-info .points {
color: var(--survival-warning);
}
- `////1`
- `/////1`
.penalty-info {
/* 1. */
display: flex; /* flex */
align-items: center; /* */
text-align: left; /* */
/* 2. "警報卡片" */
background: linear-gradient(135deg, rgba(231, 76, 60, 0.15), rgba(231, 76, 60, 0.05));
border-left: 4px solid var(--survival-danger); /* */
border-radius: 6px; /* */
/* 3. */
padding: 10px 14px;
margin-top: 12px;
/* 4. */
font-family: "Microsoft YaHei", "Segoe UI", Arial, sans-serif; /* */
font-size: 18px; /* 調 */
color: #ffdde5; /* */
font-weight: 600;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5); /* */
}
- `////1/`
- `/////`
/* 5. */
.penalty-info::before {
content: ''; /* '🛡💥💀' */
margin-right: 8px; /* */
font-size: 18px; /* */
animation: pulse-danger 2s infinite; /* */
}
- ActionResult
-
-
-
-
/* 6. "活" */
@keyframes pulse-danger {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.8; }
100% { transform: scale(1); opacity: 1; }
}
.task-divider {
height: 1px;
background: linear-gradient(90deg, transparent, var(--survival-border), transparent);
margin: 16px 0;
}
#### 8.5
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.7; }
100% { opacity: 1; }
}
##### 8.5.1
/* - */
.draw-main-task {
background: linear-gradient(135deg, rgba(52, 152, 219, 0.2), rgba(52, 152, 219, 0.1));
border-color: rgba(52, 152, 219, 0.3);
color: #3498db;
}
- 50~100
- 100~200
- 30~50
- 20~30
- 20~30
- 30~60
- 10~20
- +50~+100
- 8.5.3
- +20~+100
- +
.draw-side-task {
background: linear-gradient(135deg, rgba(243, 156, 18, 0.2), rgba(243, 156, 18, 0.1));
border-color: rgba(243, 156, 18, 0.3);
color: #f39c12;
}
.draw-container {
margin-bottom: 8px;
}
##### 8.5.2
/* */
.requirement-item.draw-ready .req-desc {
color: var(--survival-success);
font-weight: 600;
}
.requirement-item.draw-disabled .req-desc {
color: var(--survival-text);
opacity: 0.6;
}
1.
2.
.requirement-item {
cursor: pointer;
transition: all 0.2s ease;
padding: 8px 12px;
border-radius: 4px;
margin: 4px 0;
}
`{N} + [-{}-{}-:{}]`
.requirement-item:hover {
background: rgba(148, 197, 255, 0.1);
}
##### 8.5.3 2~4
.requirement-item.draw-ready:hover {
background: rgba(46, 204, 113, 0.1);
}
.requirement-item.draw-disabled {
cursor: not-allowed;
}
-
- 使使使
-
.requirement-item.draw-disabled:hover {
background: transparent;
}
- 60 ~ 150
-
-
/* - */
.target-desc.completed {
color: #999 !important;
text-decoration: line-through;
opacity: 0.7;
}
-
-
- 80 ~ 200
- 50 ~ 100
/* */
.progress-number {
color: var(--survival-warning) !important;
font-weight: bold;
}
-
-
/* */
.reward-info .points {
color: var(--survival-warning) !important;
font-weight: bold;
}
-
- 1 2 + 1
- 3 4
/* */
.time-info {
font-size: 15px;
line-height: 1.5;
color: var(--survival-text);
margin-top: 8px;
text-align: left;
}
##### 8.5.4
.time-info div {
margin-bottom: 4px;
}
-
-
- insert `//{}//-`
- replace
/* */
.penalty-info {
color: var(--survival-danger) !important;
font-weight: bold;
text-align: center;
margin-top: 8px;
}
##### 8.5.5
/* */
.item-state {
font-size: .8em;
color: var(--survival-success);
margin-top: 4px;
}
/* */
.item-props {
width: 100%;
}
- /1d100 25 1
- 1d100 40 1
.item-prop .prop-val {
word-wrap: break-word;
white-space: normal;
line-height: 1.3;
overflow-wrap: break-word;
}
-
-
/* - */
.task-strip {
position: relative;
padding: 12px 16px;
margin: 8px 0;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
text-align: center;
border: 1px solid transparent;
display: flex;
align-items: center;
justify-content: space-between;
min-height: 44px;
}
-
-
-
.task-strip:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
- `30 + [--003-:...]`
.task-strip.main-task {
background: linear-gradient(135deg, rgba(52, 152, 219, 0.2), rgba(52, 152, 219, 0.1));
border-color: rgba(52, 152, 219, 0.3);
color: #3498db;
}
- `30 + ×1`
.task-strip.side-task {
background: linear-gradient(135deg, rgba(243, 156, 18, 0.2), rgba(243, 156, 18, 0.1));
border-color: rgba(243, 156, 18, 0.3);
color: #f39c12;
}
##### 8.5.6 /
.task-strip.daily-task {
background: linear-gradient(135deg, rgba(46, 204, 113, 0.2), rgba(46, 204, 113, 0.1));
border-color: rgba(46, 204, 113, 0.3);
color: #2ecc71;
}
-
-
- = true
.task-strip.emergency-task {
background: linear-gradient(135deg, rgba(231, 76, 60, 0.2), rgba(231, 76, 60, 0.1));
border-color: rgba(231, 76, 60, 0.3);
color: #e74c3c;
animation: pulse 2s infinite;
}
/* - */
.task-status-indicator {
position: absolute;
right: 13px; /* 16px12px */
top: 50%;
transform: translateY(-50%) scale(0.9); /* 90% */
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
#### 8.6
.status-text {
font-size: 10px; /* 12px10px */
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px; /* */
transform: rotate(-15deg);
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
padding: 1px 4px; /* 2px 6px1px 4px */
border-radius: 2px;
}
使
/* */
.status-ongoing {
color: #3498db;
background: rgba(52, 152, 219, 0.15);
}
`[-{}-{}-:{}+{/}+{}]`
.status-pending {
color: #f39c12;
background: rgba(243, 156, 18, 0.15);
}
1.
2. 5-30
3.
- ///
- ///
- ......
.status-completed {
color: #2ecc71;
background: rgba(46, 204, 113, 0.15);
}
- 滿
- ...
.status-failed {
color: #e74c3c;
background: rgba(231, 76, 60, 0.15);
}
-
.status-abandoned {
color: #95a5a6;
background: rgba(149, 165, 166, 0.15);
text-decoration: line-through;
}
1.
2.
3.
/* .task-content */
.task-content {
text-align: center;
line-height: 1.4;
font-family: "Microsoft YaHei","Segoe UI",Arial,sans-serif;
font-size: 16px;
font-weight: 600;
color: inherit;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
123
/* */
.task-detail {
background: rgba(0, 0, 0, 0.15);
border-radius: 8px;
padding: 16px;
margin: 8px 0;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.task-desc {
text-align: left;
margin-bottom: 16px;
line-height: 1.4;
color: var(--survival-text);
white-space: pre-line;
word-wrap: break-word;
}
#### 8.7
.target-section {
margin: 16px 0;
}
滿
.section-title {
font-weight: 600;
margin-bottom: 8px;
color: var(--survival-accent);
}
- . = true . = false
-
- = true
.target-desc {
margin-bottom: 8px;
line-height: 1.4;
color: var(--survival-text);
white-space: pre-line;
word-wrap: break-word;
}
- . = true . = false
-
- = true
.reward-info {
color: var(--survival-text);
font-weight: 600;
margin-top: 12px;
}
.reward-info .points {
color: var(--survival-warning);
}
#### 8.8
.penalty-info {
color: var(--survival-danger);
font-weight: 600;
text-align: center;
}
1.
[]
.task-divider {
height: 1px;
background: linear-gradient(90deg, transparent, var(--survival-border), transparent);
margin: 16px 0;
}
2.
-
-
-
-
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.7; }
100% { opacity: 1; }
}
3.
Analysis
{}AI ActionResult
/* --- MAP CSS START --- */
.map-modal {
position: fixed; inset: 0; display: flex; justify-content: center; align-items: center; color: #ffffff;
background: rgba(0,0,0,0.8); backdrop-filter: blur(8px); z-index: 1000;
}
.map-modal__content {
position: relative; width: 95vw; height: 95vh; padding: 0; overflow: hidden; display: flex; flex-direction: column;
border-radius: 26px; border: 1px solid rgba(148, 197, 255, 0.18);
background: linear-gradient(155deg, rgba(17, 28, 45, 0.94), rgba(24, 36, 58, 0.94));
box-shadow: var(--survival-shadow); backdrop-filter: blur(20px) saturate(160%);
animation: modalFadeIn .3s ease-out;
}
.map-modal__close {
position:absolute; top:10px; right:15px; font-size:24px; cursor:pointer;
color:rgba(239, 246, 255, 0.7); transition:all .2s ease;
width:30px; height:30px; display:flex; align-items:center; justify-content:center; border-radius:50%; z-index: 1100;
}
.map-modal__close:hover{ color:var(--survival-danger); background:rgba(231,76,60,.2); transform:scale(1.1) }
4.
. true
.map-modal .map-container {
flex: 1; position: relative; overflow: hidden; touch-action: none; background: #2a2a2a;
cursor: grab;
}
.map-modal .map-container.linking { cursor: crosshair; }
.map-modal .map-container.dragging { cursor: grabbing; }
.map-modal .info-panel, .map-modal .zoom-controls button {
border-color: rgba(148, 197, 255, 0.2);
background: rgba(24, 36, 58, 0.9);
box-shadow: 0 12px 28px rgba(6, 12, 25, 0.45);
}
.map-modal .zoom-btn:hover {
background: rgba(94, 161, 255, 0.25);
transform: translateY(-3px) scale(1.05);
}
/* --- MAP CSS END --- */
/* --- Draw Confirmation Modal --- */
.draw-confirm-modal { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: radial-gradient(circle at center, rgba(41, 128, 185, 0.38), rgba(10, 14, 22, 0.92)); backdrop-filter: blur(10px); z-index: 10000; animation: fadeInModal 0.25s ease; }
.draw-confirm-modal__content {
position: relative; width: min(420px, 90vw); overflow: hidden; text-align: center;
border-radius: 26px; border: 1px solid rgba(148, 197, 255, 0.18);
background: linear-gradient(155deg, rgba(17, 28, 45, 0.94), rgba(24, 36, 58, 0.94));
box-shadow: var(--survival-shadow); backdrop-filter: blur(20px) saturate(160%);
padding: 28px 26px 24px;
}
.draw-confirm-modal__glow { position: absolute; inset: -45%; background: radial-gradient(circle, rgba(77, 208, 255, 0.35) 0%, transparent 65%); filter: blur(60px); opacity: 0.65; animation: modalGlow 6s ease-in-out infinite; pointer-events: none; }
.draw-confirm-modal__title { position: relative; z-index: 1; font-size: 20px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: #e9f5ff; margin: 0 0 12px; }
.draw-confirm-modal__desc { position: relative; z-index: 1; font-size: 15px; color: var(--survival-text); margin: 0 0 18px; }
.draw-confirm-modal__points { position: relative; z-index: 1; font-size: 14px; color: var(--survival-muted); letter-spacing: 0.05em; margin-bottom: 24px; }
.draw-confirm-modal__points span { display: inline-block; margin-top: 6px; font-size: 30px; font-weight: 700; color: #4dd0ff; text-shadow: 0 0 18px rgba(77, 208, 255, 0.55); }
.draw-confirm-modal__actions { position: relative; z-index: 1; display: flex; gap: 12px; justify-content: center; margin-top: 10px; }
.draw-confirm-modal__button { flex: 1; padding: 12px 16px; border-radius: 999px; border: none; font-size: 15px; font-weight: 600; cursor: pointer; transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease; font-family: "Inter", "Microsoft YaHei", sans-serif;}
.draw-confirm-modal__button:active { transform: scale(0.96); }
.draw-confirm-modal__confirm { background: linear-gradient(135deg, #26c6da, #7c4dff); color: #fff; box-shadow: 0 12px 34px rgba(124, 77, 255, 0.35); }
.draw-confirm-modal__confirm:hover:not(.is-disabled) { transform: translateY(-1px); box-shadow: 0 16px 42px rgba(124, 77, 255, 0.48); }
.draw-confirm-modal__cancel { background: rgba(37, 49, 68, 0.9); color: var(--survival-text); box-shadow: 0 12px 28px rgba(0, 0, 0, 0.35); }
.draw-confirm-modal__cancel:hover { transform: translateY(-1px); box-shadow: 0 14px 32px rgba(0, 0, 0, 0.4); }
.draw-confirm-modal__confirm.is-disabled { background: rgba(90, 96, 112, 0.7); color: var(--survival-text); cursor: not-allowed; box-shadow: none; }
.draw-confirm-modal__confirm.is-loading { color: transparent; position: relative; }
.draw-confirm-modal__confirm.is-loading::after { content: ''; position: absolute; top: 50%; left: 50%; width: 22px; height: 22px; margin: -11px 0 0 -11px; border: 2px solid rgba(255, 255, 255, 0.32); border-top-color: #ffffff; border-radius: 50%; animation: spin 0.7s linear infinite; }
.draw-confirm-modal__status { position: relative; z-index: 1; margin-top: 20px; min-height: 18px; font-size: 13px; color: var(--survival-text); letter-spacing: 0.03em; }
@keyframes fadeInModal { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
@keyframes modalGlow { 0% { transform: scale(0.8); opacity: 0.5; } 50% { transform: scale(1.1); opacity: 0.7; } 100% { transform: scale(0.8); opacity: 0.5; } }
@keyframes spin { to { transform: rotate(360deg); } }
/* --- Image Viewer Modal --- */
.image-viewer-modal { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 30px; background: radial-gradient(circle at 20% 20%, rgba(46, 134, 222, 0.35), transparent 55%), rgba(8, 11, 19, 0.92); backdrop-filter: blur(12px); z-index: 9990; animation: fadeInModal 0.25s ease; }
.image-viewer-modal__content {
position: relative; width: min(960px, 94vw); height: min(82vh, 700px); display: flex; flex-direction: column; overflow: hidden;
border-radius: 26px; border: 1px solid rgba(148, 197, 255, 0.18);
background: linear-gradient(155deg, rgba(17, 28, 45, 0.94), rgba(24, 36, 58, 0.94));
box-shadow: var(--survival-shadow); backdrop-filter: blur(20px) saturate(160%);
}
.image-viewer__header { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px 12px; color: #e9f5ff; }
.image-viewer__title { font-size: 18px; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }
.image-viewer__close { background: none; border: none; font-size: 22px; cursor: pointer; transition: transform 0.2s ease, color 0.2s ease; color: var(--survival-muted); }
.image-viewer__close:hover { color: #ffffff; transform: rotate(90deg); }
.image-viewer__canvas {
position: relative; flex: 1; margin: 0 24px 24px; overflow: hidden; touch-action: none;
background: radial-gradient(circle at 35% 30%, rgba(94, 161, 255, 0.14), rgba(9, 13, 22, 0.92));
border: 1px solid rgba(148, 197, 255, 0.16);
border-radius: 14px; cursor: grab;
}
.image-viewer__canvas.is-grabbing { cursor: grabbing; }
.image-viewer__image { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(1); transform-origin: center center; max-width: none; max-height: none; will-change: transform; pointer-events: none; user-select: none; }
.image-viewer__placeholder { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 70%; max-width: 360px; text-align: center; font-size: 14px; line-height: 1.6; pointer-events: none; color: var(--survival-text); }
.image-viewer__status { position: absolute; left: 24px; bottom: 18px; font-size: 13px; letter-spacing: 0.02em; color: var(--survival-text); }
.image-viewer__toolbar { display: flex; align-items: center; gap: 12px; padding: 0 24px 16px; flex-wrap: wrap; }
.image-viewer__controls { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }
.image-viewer__hint { flex: 1 1 auto; font-size: 13px; line-height: 1.5; min-width: 200px; color: var(--survival-text);}
.image-viewer__hint strong { color: #fff;}
.image-viewer__control-button {
width: 38px; height: 38px; border-radius: 50%; border: none; font-size: 16px; cursor: pointer;
background: rgba(32, 43, 60, 0.85); color: var(--survival-text);
transition: transform 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
font-family: "Inter", "Microsoft YaHei", sans-serif;
}
.image-viewer__control-button:hover { transform: translateY(-1px); background: rgba(77, 208, 255, 0.2); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.35); }
#### 8.9
.temp-fill { position: absolute; top: 0; left: 0; height: 100%; border-radius: 8px; background-image: linear-gradient(90deg, var(--survival-accent), var(--survival-success)); opacity: .55; }
-
-
@media (max-width: 720px) {
.image-viewer-modal { padding: 18px; }
.image-viewer-modal__content { height: 88vh; }
.image-viewer__toolbar { flex-direction: column; align-items: stretch; }
.image-viewer__hint { margin-bottom: 8px; }
.image-viewer__controls { margin-left: 0; }
.image-viewer__canvas { margin: 0 18px 18px; }
}
### 9.
@media (max-width: 480px) {
.draw-confirm-modal__content { padding: 24px 18px 20px; }
.draw-confirm-modal__actions { flex-direction: column; }
.image-viewer__header { padding: 16px 18px 10px; }
.image-viewer-modal__content { border-radius: 16px; }
}
<>使 insert /-使 replace使 remove replace
.other-group { margin-top: 8px; }
.other-card { background: rgba(0,0,0,.15); padding: 8px 10px; border-radius: 6px; border: 1px solid var(--survival-border); margin-bottom: 6px; }
.other-card__title { font-weight: 700; margin-bottom: 4px; }
.empty-text { opacity: .75; font-size: 13px; }
### 10.
/* --- --- */
.love-progress .progress__bar {
background-image: linear-gradient(90deg, #FF8FB1, #FFCAD4); /* : */
box-shadow: 0 0 18px rgba(255, 143, 177, 0.55);
}
.desire-progress .progress__bar {
background-image: linear-gradient(90deg, #E94057, #F27121); /* : */
box-shadow: 0 0 18px rgba(233, 64, 87, 0.55);
}
.dev-progress .progress__bar {
background-image: linear-gradient(90deg, #C39BD3, #8E44AD); /* : */
box-shadow: 0 0 18px rgba(142, 68, 173, 0.55);
}
.crevice-progress .progress__bar {
background-image: linear-gradient(90deg, #485461, #28313b); /* : */
box-shadow: 0 0 18px rgba(40, 49, 59, 0.55);
}
.health-progress .progress__bar {
background-image: linear-gradient(90deg, #58f0a7, #1abc9c); /* - */
box-shadow: 0 0 18px rgba(46, 204, 113, 0.45);
}
.satiety-progress .progress__bar {
background-image: linear-gradient(90deg, #ffdc84, #ff9f6c); /* - */
box-shadow: 0 0 18px rgba(243, 156, 18, 0.45);
}
.fatigue-progress .progress__bar {
background-image: linear-gradient(90deg, #95a5a6, #7f8c8d); /* - */
box-shadow: 0 0 18px rgba(127, 140, 141, 0.45);
}
.water-progress .progress__bar {
background-image: linear-gradient(90deg, #7fd8ff, #5ea1ff); /* - */
box-shadow: 0 0 18px rgba(94, 161, 255, 0.45);
}
####
/* --- --- */
.companion-inventory-grid {
display: grid;
/* 4 */
grid-template-columns: repeat(4, 1fr);
gap: 12px; /* */
margin-top: 20px; /* */
}
- 00:00
- ----<>
- 使replace
/* */
@media (max-width: 960px) {
.companion-inventory-grid {
grid-template-columns: repeat(3, 1fr); /* 3 */
}
}
@media (max-width: 640px) {
.companion-inventory-grid {
grid-template-columns: repeat(2, 1fr); /* 2 */
}
}
####
/* --- v4.0--- */
/* 1: */
.task-card > .task-body.collapsible__body {
display: none;
}
1. `//`
2.
3.
- ----
-
- --
4. replace
/* 2: 'active' */
.task-card.active > .task-body.collapsible__body {
display: block;
}
/* 🔴 - 3 */
.crop-status-danger {
color: #ff4757;
background: rgba(255, 71, 87, 0.15);
}
####
/* 🟢 - > 3 */
.crop-status-ready {
color: #58f0a7;
background: rgba(88, 240, 167, 0.15);
}
/* ============== ============== */
.crop-status-indicator {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
padding: 2px 6px;
border-radius: 4px;
margin-left: 12px;
}
.crop-status-ready {
color: #58f0a7;
background: rgba(88, 240, 167, 0.15);
}
.crop-status-growing {
color: #a0aec0;
background: rgba(160, 174, 192, 0.15);
}
.item-name .crop-status-indicator { /* */
transform: scale(0.9);
}
🔴 ActionResult
/* ============== ============== */
.livestock-status-indicator {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
padding: 2px 6px;
border-radius: 4px;
margin-left: 12px;
}
.livestock-status-harvest {
color: #58f0a7; /* - */
background: rgba(88, 240, 167, 0.15);
}
.livestock-status-breed {
color: #3498db; /* - */
background: rgba(52, 152, 219, 0.15);
}
.livestock-status-both {
color: #f39c12; /* - */
background: rgba(243, 156, 18, 0.15);
}
.livestock-status-none {
color: #a0aec0; /* - */
background: rgba(160, 174, 192, 0.15);
}
.item-name .livestock-status-indicator { /* */
transform: scale(0.9);
}
-
- `//`
- `{}`
-
- :[]
-
/* ============== ============== */
.crop-acceleration-info {
padding: 16px;
margin-bottom: 20px;
border-radius: 12px;
background: rgba(30, 45, 70, 0.8);
border: 1px solid var(--survival-glass-border);
box-shadow: inset 0 1px 2px rgba(0,0,0,0.4), var(--survival-glow);
}
.crop-acceleration-info__title {
font-size: 15px;
font-weight: 700;
color: var(--survival-accent-strong);
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.crop-acceleration-info__item {
font-size: 14px;
padding-left: 28px;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 6px;
}
.crop-acceleration-info__total {
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid var(--survival-border);
font-size: 16px;
font-weight: 700;
color: var(--survival-success);
display: flex;
align-items: center;
gap: 8px;
}
### 11. //
/* ============== ============== */
.loyalty-progress .progress__bar {
background-image: linear-gradient(90deg, #FFD700, #FFA500); /* : */
box-shadow: 0 0 18px rgba(255, 215, 0, 0.45);
}
.pet-health-progress .progress__bar {
background-image: linear-gradient(90deg, #27ae60, #16a085); /* : */
box-shadow: 0 0 18px rgba(46, 204, 113, 0.45);
}
.pet-desire-progress .progress__bar {
background-image: linear-gradient(90deg, #E94057, #F27121); /* : */
box-shadow: 0 0 18px rgba(233, 64, 87, 0.45);
}
/* // */
.task-strip {
position: relative;
padding: 12px 16px;
margin: 8px 0;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
text-align: center;
border: 1px solid transparent;
display: flex;
align-items: center;
justify-content: space-between;
min-height: 44px;
}
.task-strip:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.task-strip.main-task {
background: linear-gradient(135deg, rgba(52, 152, 219, 0.2), rgba(52, 152, 219, 0.1));
border-color: rgba(52, 152, 219, 0.3);
color: #3498db;
}
.task-strip.side-task {
background: linear-gradient(135deg, rgba(243, 156, 18, 0.2), rgba(243, 156, 18, 0.1));
border-color: rgba(243, 156, 18, 0.3);
color: #f39c12;
}
.task-strip.bond-task {
background: linear-gradient(135deg, rgba(189, 147, 249, 0.25), rgba(189, 147, 249, 0.15));
border-color: rgba(142, 68, 173, 0.4);
color: #f0e6ff;
}
.task-content {
text-align: center;
line-height: 1.4;
font-size: 16px;
font-weight: 600;
width: 100%;
}
.task-detail {
background: rgba(0, 0, 0, 0.15);
border-radius: 8px;
padding: 16px;
margin: 8px 0;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.collapse-button {
width: 100%;
padding: 8px 12px;
margin-top: 15px;
background: rgba(0,0,0,.2);
border: 1px solid var(--survival-border);
border-radius: 8px;
color: var(--survival-warning);
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.2s ease;
}
.collapse-button:hover {
background: rgba(52,73,94,.6);
border-color: var(--survival-warning);
}
/* - */
.progress-knowledge-card {
font-size: 14px;
}
.progress-knowledge-card .progress-wrapper > div:first-child,
.progress-knowledge-card .mini-progress__text {
font-size: 14px !important;
}
.progress-knowledge-card .progress__bar,
.progress-knowledge-card .mini-progress__bar {
height: 10px; /* */
}
.progress-knowledge-card .item-prop {
font-size: 14px !important;
}
.progress-knowledge-card .prop-key,
.progress-knowledge-card .prop-val {
font-size: 14px !important;
}
.progress-knowledge-card .skill-desc,
.progress-knowledge-card .task-desc {
font-size: 14px !important;
}
.progress-knowledge-card .collapse-button {
font-size: 14px !important;
padding: 10px 12px;
}
/* */
.progress-knowledge-card .task-strip .task-content {
font-size: 16px !important;
}
/* */
.progress-knowledge-card div[style*="font-size"],
.progress-knowledge-card span[style*="font-size"] {
font-size: 14px !important;
}
/* - */
.progress-knowledge-card {
font-size: 15px !important;
}
.progress-knowledge-card * {
font-size: 15px !important;
}
/* 12/100 */
.progress-knowledge-card .progress-wrapper > div:first-child,
.progress-knowledge-card .progress-wrapper > div {
font-size: 15px !important;
color: #ffffff !important;
}
.progress-knowledge-card .progress-wrapper .progress-number {
color: var(--survival-warning) !important;
font-weight: bold !important;
}
/* */
.progress-knowledge-card div[style*="font-size"],
.progress-knowledge-card span[style*="font-size"],
.progress-knowledge-card div[style*="font-size"] *,
.progress-knowledge-card span[style*="font-size"] * {
font-size: 15px !important;
}
/* */
.progress-knowledge-card .skill-desc,
.progress-knowledge-card .task-desc,
.progress-knowledge-card .item-prop,
.progress-knowledge-card .item-prop .prop-key,
.progress-knowledge-card .item-prop .prop-val,
.progress-knowledge-card .detail-line,
.progress-knowledge-card .sub-line {
font-size: 15px !important;
color: #cccccc !important;
}
/* / */
.progress-knowledge-card .material-value,
.progress-knowledge-card .detail-line span:last-child,
.progress-knowledge-card .sub-line span:last-child {
color: var(--survival-warning) !important;
font-weight: bold !important;
}
/* */
.progress-knowledge-card .completed,
.progress-knowledge-card .detail-line.completed,
.progress-knowledge-card .sub-line.completed {
color: #888888 !important;
text-decoration: line-through !important;
}
/* */
.progress-knowledge-card .field-title {
font-size: 15px !important;
font-weight: bold !important;
color: var(--survival-accent) !important;
margin-top: 8px !important;
margin-bottom: 4px !important;
}
/* */
.progress-knowledge-card .progress,
.progress-knowledge-card .mini-progress {
height: 10px !important;
}
.progress-knowledge-card .progress__bar,
.progress-knowledge-card .mini-progress__bar {
height: 10px !important;
}
/* */
.progress-knowledge-card .collapse-button {
font-size: 15px !important;
padding: 10px 12px;
}
/* / */
.progress-knowledge-card .task-content {
font-size: 16px !important;
}
</style></head><body><div id="survival-ui" class="survival-ui" tabindex="0"></div><script>
####
AI
function formatBonusValue(value) {
if (!value || typeof value !== 'object') {
return textify(value, '');
}
const bonusEntries = [];
Object.entries(value).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
return bonusEntries.join('');
}
####
- AI
-
-
function parseTimeToMinutes(timeString) {
const dayMatch = timeString.match(/(\d+)/);
const timeMatch = timeString.match(/(\d{2}):(\d{2})/);
####
if (!dayMatch || !timeMatch) {
return null; // 格式不對就直接放棄
}
- **user**
- `<sex_rules>`
-
1.
2.
3.
4. `//[]//(<user>)`
5. : delta : insert
const days = parseInt(dayMatch[1], 10);
const hours = parseInt(timeMatch[1], 10);
const minutes = parseInt(timeMatch[2], 10);
#### .
return (days * 24 * 60) + (hours * 60) + minutes;
}
滿
- <user>
-
- /2050
-
// 2. 化妝師:把剩餘的總分鐘數,變成 "X天X小時X分"
function formatRemainingTime(totalMinutes) {
if (totalMinutes <= 0) {
return "已截止";
}
- : replace
- : 30-60
- /
- <user>
-
const days = Math.floor(totalMinutes / (24 * 60));
const hours = Math.floor((totalMinutes % (24 * 60)) / 60);
const minutes = totalMinutes % 60;
-
-
-
let result = "";
if (days > 0) result += `${days}`;
if (hours > 0) result += `${hours}`;
if (minutes > 0) result += `${minutes}`;
####
return result.trim();
}
滿
// --- 新增的狀態描述函數 ---
function getFavorabilityStatus(value) {
if (value < 0) return "仇人";
if (value >= 0 && value <= 20) return "陌生人";
if (value > 20 && value <= 40) return "疏離淡漠";
if (value > 40 && value <= 50) return "平淡如水";
if (value > 50 && value <= 60) return "親近信賴";
if (value > 60 && value <= 70) return "依賴眷戀";
if (value > 70 && value <= 99) return "熱戀痴迷";
if (value >= 100) return "摯愛不渝";
return "";
}
-
- /
-
function getDesireStatus(value) {
if (value >= 0 && value <= 20) return "沒感覺";
if (value > 20 && value <= 40) return "心動";
if (value > 40 && value <= 60) return "期待愛撫";
if (value > 60 && value <= 80) return "渴望性愛";
if (value > 80 && value < 100) return "強烈慾望";
if (value >= 100) return "失控狂熱";
return "";
}
-
- /
function getHealthStatus(value) {
if (value === 0) return "死亡";
if (value > 0 && value <= 10) return "重傷昏迷";
if (value > 10 && value <= 30) return "生病";
if (value > 30 && value <= 60) return "虛弱";
if (value > 60 && value <= 100) return "健康";
if (value > 100) return "超人";
return "狀態未知";
}
-
-
-
function getCreviceStatus(value) {
if (value >= 0 && value <= 30) return "萌芽期";
if (value > 30 && value <= 60) return "依賴期";
if (value > 60 && value < 100) return "渴望期";
if (value >= 100) return "崩塌期";
return "";
}
- : insert
- : `{"事件名稱": {"描述": "簡要描述(30字以內)"}}`
// --- 寵物狀態描述函數 ---
function getLoyaltyStatus(value) {
if (value < 0) return "敵對";
if (value >= 0 && value <= 20) return "警惕";
if (value > 20 && value <= 40) return "中立";
if (value > 40 && value <= 60) return "友善";
if (value > 60 && value <= 80) return "信賴";
if (value > 80 && value < 100) return "忠誠";
if (value >= 100) return "絕對忠誠";
return "";
}
:
function getPetHealthStatus(value) {
if (value === 0) return "死亡";
if (value > 0 && value <= 20) return "瀕危";
if (value > 20 && value <= 40) return "重傷";
if (value > 40 && value <= 60) return "受傷";
if (value > 60 && value <= 80) return "健康";
if (value > 80 && value <= 100) return "充滿活力";
if (value > 100) return "超凡";
return "狀態未知";
}
// --- 狀態描述函數結束 ---
function normalizeValue(value) {
if (Array.isArray(value)) {
const flattened = [];
value.forEach((item) => {
if (Array.isArray(item)) {
const inner = normalizeValue(item);
if (Array.isArray(inner)) {
flattened.push(...inner);
} else if (inner !== '' && inner !== undefined && inner !== null) {
flattened.push(inner);
}
} else if (item !== undefined && item !== null && item !== '') {
flattened.push(item);
}
});
if (flattened.length === 0) {
return '';
}
if (flattened.length === 1) {
return normalizeValue(flattened[0]);
}
return flattened;
}
return value;
}
####
function e(value, parse = true) {
if (value == null) {
return '';
}
const normalized = normalizeValue(value);
if (Array.isArray(normalized)) {
const processed = normalized
.map((item) => e(item, parse))
.filter((item) => item !== '' && item !== undefined && item !== null);
if (processed.length === 0) {
return parse ? '' : [];
}
return parse ? processed.join(' / ') : processed;
}
if (typeof normalized === 'string' && normalized.includes('->')) {
const match = normalized.match(/(.+)->(.+)\((.+)\)/);
if (match) {
const label = match[2].trim();
return parse ? a(label) : label;
}
}
return parse ? a(normalized) : normalized;
}
滿
- B
-
-
function a(value) {
if (typeof value === 'number') {
return value;
}
if (typeof value === 'string') {
const cleaned = value.replace(/,/g, '');
const parsed = parseFloat(cleaned);
if (!Number.isNaN(parsed)) {
return parsed;
}
}
return value;
}
:
function isMetaOnlyObject(value) {
return (
value &&
typeof value === 'object' &&
!Array.isArray(value) &&
'$meta' in value &&
Object.keys(value).length === 1
);
}
- : insert replace
- : `{"部位名稱": {"刺激方式": "反應描述"}}`
function textify(value, fallback = '') {
const raw = e(value, false);
if (Array.isArray(raw)) {
const list = raw.map((item) => textify(item, '')).filter(Boolean);
return list.length > 0 ? list.join(' / ') : fallback;
}
if (raw == null) {
return fallback;
}
const str = String(raw).trim();
return str || fallback;
}
####
function toEntries(source) {
if (source == null) {
return [];
}
const raw = e(source, false);
if (Array.isArray(raw)) {
const result = [];
raw.forEach((item, index) => {
if (item == null) {
return;
}
if (Array.isArray(item)) {
item.forEach((nested, nestedIndex) => {
if (nested == null || isMetaOnlyObject(nested)) {
return;
}
result.push([`${index}-${nestedIndex}`, nested]);
});
return;
}
if (isMetaOnlyObject(item)) {
return;
}
result.push([String(index), item]);
});
return result;
}
if (typeof raw === 'object') {
return Object.entries(raw).filter(([key, value]) => {
if (key === '$meta') {
return false;
}
if (isMetaOnlyObject(value)) {
return false;
}
return value != null;
});
}
return [['0', raw]];
}
滿
-
- 2
function firstMeaningfulObject(source) {
if (source && typeof source === 'object' && !Array.isArray(source)) {
const clone = { ...source };
delete clone.$meta;
if (Object.keys(clone).length > 0) {
return clone;
}
}
const entries = toEntries(source);
for (const [, value] of entries) {
if (value && typeof value === 'object' && !Array.isArray(value)) {
const clone = { ...value };
delete clone.$meta;
return clone;
}
}
return {};
}
- : insert replace
- : `{"癖好名稱": "描述說明"}`
function ensureValueArray(value) {
return toEntries(value).map(([, item]) => item);
}
const s = {
: 2000,
: 100000,
: 200,
: 2400,
: 100,
: 100,
: 100,
: 42,
: 100,
: 100,
: 100,
: 100,
: 100,
: 100,
: 100,
: 100,
};
function t(label, current, max, className) {
const percent = Math.max(0, Math.min(100, max === 0 ? 0 : (current / max) * 100));
const wrapper = $('<div>').addClass('progress-wrapper');
const displayText = label.includes('/') ? label : (label ? `${label}: ${current}/${max}` : `${current}/${max}`);
$('<div>').text(displayText).appendTo(wrapper);
const bar = $('<div>').addClass('progress');
if (className) {
bar.addClass(className);
}
$('<div>').addClass('progress__bar').css('width', `${percent}%`).appendTo(bar);
wrapper.append(bar);
return wrapper;
}
####
function d(title, expanded = false) {
const section = $('<section>').addClass('collapsible');
if (expanded) {
section.addClass('active');
}
const header = $('<div>').addClass('collapsible__header'); // 我們會在後面添加內容
const body = $('<div>').addClass('collapsible__body');
// 將標題本身放在一個 span 裡,方便和標籤並存
$('<span>').text(title).appendTo(header);
if (expanded) {
body.css('display', 'block');
}
header.on('click', () => {
section.toggleClass('active');
body.slideToggle(200);
});
section.append(header, body);
return { $section: section, $header: header, $body: body };
}
: /
: replace
function n(title, items, expanded = false) {
const section = $('<section>').addClass('collapsible');
if (expanded) {
section.addClass('active');
}
const header = $('<div>').addClass('collapsible__header collapsible__header--with-progress');
$('<span>').addClass('collapsible__title').text(title).appendTo(header);
const bars = $('<div>').addClass('collapsible__bars-container');
items.forEach((item) => {
const row = $('<div>').addClass('progress-item');
$('<span>').addClass('progress-label').text(`${item.label}:`).appendTo(row);
const percent = Math.max(0, Math.min(100, item.max === 0 ? 0 : (item.current / item.max) * 100));
const miniWrapper = $('<div>').addClass('mini-progress-wrapper');
const miniBar = $('<div>').addClass('mini-progress');
if (item.className) {
miniBar.addClass(item.className);
}
$('<div>').addClass('mini-progress__bar').css('width', `${percent}%`).appendTo(miniBar);
$('<div>').addClass('mini-progress__text').text(`${item.current}/${item.max}`).appendTo(miniWrapper);
miniWrapper.append(miniBar);
row.append(miniWrapper);
bars.append(row);
});
header.append(bars);
$('<span>').addClass('collapsible__indicator').appendTo(header);
const body = $('<div>').addClass('collapsible__body');
if (expanded) {
body.css('display', 'block');
}
header.on('click', () => {
section.toggleClass('active');
body.slideToggle(200);
});
section.append(header, body);
return { $section: section, $body: body };
}
####
function i(equipmentSource, itemsSource, campSource, currentWeight, weightLimit, showCamp = true) {
const modal = $('<div>').addClass('inventory-modal');
const content = $('<div>').addClass('inventory-modal__content');
const close = $('<span>').addClass('inventory-modal__close').html('×').on('click', () => modal.remove());
const weightContainer = $('<div>').addClass('weight-container');
const percent = Math.max(0, Math.min(100, weightLimit === 0 ? 0 : (currentWeight / weightLimit) * 100));
const weightBar = $('<div>').addClass('vertical-progress');
$('<div>').addClass('vertical-progress__bar').css('height', `${percent}%`).appendTo(weightBar);
$('<div>').addClass('vertical-progress__label').text('').appendTo(weightBar);
$('<div>').addClass('vertical-progress__value').text(`${currentWeight.toFixed(1)}/${weightLimit}kg`).appendTo(weightBar);
weightContainer.append(weightBar);
const body = $('<div>').addClass('inventory-content');
function renderItemCollection(title, source, isListLayout = false) {
body.append($('<h3>').text(title));
// --- 特殊處理:裝備欄(顯示為單一裝備欄)---
if (title === '') {
// 創建裝備欄容器
const equipmentGrid = $('<div>').addClass('inventory-grid equipment-grid').css({
'grid-template-columns': 'repeat(5, 1fr)', // 一行5個
'gap': '15px'
});
// 定義裝備部位順序
const equipmentSlots = [
'', '', '', '', '',
'', '', '', '', ''
];
equipmentSlots.forEach((slot, index) => {
const slotContainer = $('<div>').addClass('equipment-slot')
.attr('data-slot', slot)
.css({
'background': 'var(--survival-surface-strong)',
'border': '1px solid var(--survival-glass-border)',
'border-radius': '12px',
'padding': '16px',
'text-align': 'center',
'transition': 'all 0.25s ease-out',
'min-height': '140px', // 稍微增高
'display': 'flex',
'flex-direction': 'column',
'justify-content': 'flex-start' // 從頂部開始
});
// 添加排序
slotContainer.css('order', index + 1);
// 裝備部位標題
const slotTitle = $('<div>').addClass('slot-title').css({
'font-size': '20px',
'font-weight': '700',
'color': '#d17d2e',
'letter-spacing': '0.05em',
'text-transform': 'uppercase',
'margin-bottom': '12px',
'padding-bottom': '8px',
'border-bottom': '1px solid rgba(148, 197, 255, 0.2)',
'line-height': '1.2'
}).text(slot);
slotContainer.append(slotTitle);
// 檢查該部位是否有裝備
const equipmentItem = source[slot];
if (equipmentItem && typeof equipmentItem === 'object' && Object.keys(equipmentItem).length > 0) {
// 獲取裝備名稱(第一個鍵名)
const itemKey = Object.keys(equipmentItem)[0];
const itemData = equipmentItem[itemKey];
if (itemKey && itemData) {
const itemNameDiv = $('<div>').addClass('equipment-item-name').css({
'font-size': '18px',
'font-weight': '600',
'color': 'var(--survival-accent-strong)',
'margin-bottom': '8px',
'word-wrap': 'break-word',
'line-height': '1.3'
}).text(itemKey);
itemNameDiv.append(
$('<span>').addClass('corner-decor corner-tl'),
$('<span>').addClass('corner-decor corner-tr'),
$('<span>').addClass('corner-decor corner-bl'),
$('<span>').addClass('corner-decor corner-br')
);
slotContainer.append(itemNameDiv);
// 顯示裝備屬性
const itemProps = $('<div>').addClass('equipment-item-props').css({
'font-size': '12px',
'color': 'var(--survival-text)',
'opacity': '0.8',
'text-align': 'left',
'line-height': '1.4'
});
// 完整的屬性顯示邏輯
const orderedProps = ['', '', '', ''];
const attributes = new Map();
// 先按照順序處理
orderedProps.forEach(k => {
if (itemData.hasOwnProperty(k)) {
attributes.set(k, itemData[k]);
}
});
// 處理狀態類型和狀態
const stateType = textify(itemData[''] ?? '', '');
if (stateType && itemData.hasOwnProperty('')) {
// 如果狀態類型不是'耐久度',或者還沒有設置耐久度,則添加
if (stateType.toLowerCase() !== '' || !attributes.has('')) {
attributes.set(stateType, itemData['']);
}
}
// 處理其他屬性
Object.entries(itemData).forEach(([k, v]) => {
if (!attributes.has(k) && k !== '$meta' && k !== '' && k !== '') {
if (k === '' && v && typeof v === 'object') {
// 創建加值描述文字
const bonusEntries = [];
Object.entries(v).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
attributes.set(k, bonusEntries.join(''));
} else {
attributes.set(k, v);
}
}
});
// 顯示所有屬性
attributes.forEach((v, k) => {
if (v !== null && v !== '' && v !== undefined) {
const line = $('<div>').addClass('item-prop equipment-prop');
line.attr('data-prop', k);
// 如果是加值欄位,添加特殊類別
if (k === '') {
line.addClass('bonus-prop');
// 在加值前面添加分隔線
const separator = $('<div>').addClass('bonus-separator').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '10px 0 8px 0',
'width': '100%'
});
itemProps.append(separator);
}
let displayValue = textify(v, '');
if (k === '' && typeof v === 'number') {
displayValue += 'kg';
}
if (k === '') {
displayValue = String(displayValue);
}
if (k === '' && displayValue.length > 80) {
displayValue = displayValue.substring(0, 77) + '...';
}
$('<span>').addClass('prop-key').text(String(k)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
$('<span>').addClass('prop-val').text(displayValue).appendTo(line);
itemProps.append(line);
// 如果是加值欄位,在後面也添加一個小分隔線
if (k === '') {
const bottomSeparator = $('<div>').css({
'height': '1px',
'background': 'rgba(148, 197, 255, 0.1)',
'margin': '8px 0 4px 0',
'width': '100%'
});
itemProps.append(bottomSeparator);
}
}
});
if (attributes.size > 0) {
slotContainer.append(itemProps);
}
// 懸停效果
slotContainer.hover(
function() {
$(this).css({
'transform': 'translateY(-3px)',
'box-shadow': '0 5px 15px rgba(0,0,0,.3)',
'background': 'rgba(52,73,94,.9)',
'border-color': 'var(--survival-accent)'
});
},
function() {
$(this).css({
'transform': 'translateY(0)',
'box-shadow': 'none',
'background': 'var(--survival-surface-strong)',
'border-color': 'var(--survival-glass-border)'
});
}
);
}
} else {
// 該部位沒有裝備
const emptyText = $('<div>').addClass('equipment-empty').css({
'font-size': '20px'
}).text('');
slotContainer.append(emptyText);
}
equipmentGrid.append(slotContainer);
});
body.append(equipmentGrid);
return;
}
// --- 裝備欄特殊處理結束 ---
const container = isListLayout ? $('<div>').addClass('inventory-list') : $('<div>').addClass('inventory-grid');
const entries = toEntries(source);
if (entries.length === 0) {
container.append(isListLayout ? $('<p>').addClass('empty-text').text('') : $('<div>').addClass('inventory-item empty-text').text(''));
} else {
entries.forEach(([key, value]) => {
if (value && typeof value === 'object') {
const itemCard = isListLayout ? $('<div>').addClass('inventory-list-item') : $('<div>').addClass('inventory-item');
$('<div>').addClass('item-name').text(String(key)).appendTo(itemCard);
const props = $('<div>').addClass('item-props');
// --- 這是新手把手教你的邏輯 ---
const orderedProps = [
'', '', '', ''
];
// 處理狀態類型和狀態,把 '耐久度' 這種情況也包含進來
const stateType = textify(value[''] ?? '', '');
if (stateType && !orderedProps.includes(stateType)) {
orderedProps.push(stateType);
}
orderedProps.forEach(key => {
let val = value[key];
// 特殊處理狀態
if (key === stateType) {
val = value[''];
}
if (val !== null && val !== undefined && val !== '') {
const line = $('<div>').addClass('item-prop');
$('<span>').addClass('prop-key').text(String(key)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
let displayValue = textify(val, '');
if (key === '' && typeof val === 'number') {
displayValue += 'kg';
}
$('<span>').addClass('prop-val').text(displayValue).appendTo(line);
props.append(line);
}
});
// 處理剩下的屬性,比如'描述'
Object.entries(value).forEach(([key, val]) => {
// 檢查這個屬性是不是我們已經手動處理過的
if (!orderedProps.includes(key) && key !== '$meta' && key !== '' && key !== '' && key !== stateType) {
if (val !== null && val !== undefined && val !== '') {
const line = $('<div>').addClass('item-prop');
// 如果是加值欄位,添加特殊類別
if (key === '') {
line.addClass('bonus-prop');
// 在加值前面添加分隔線
const separator = $('<div>').addClass('bonus-separator').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '10px 0 8px 0',
'width': '100%'
});
props.append(separator);
}
$('<span>').addClass('prop-key').text(String(key)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
let displayValue = '';
if (key === '' && val && typeof val === 'object') {
// 處理加值物件
const bonusEntries = [];
Object.entries(val).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
displayValue = bonusEntries.join('');
} else {
displayValue = textify(val, '');
if (key === '' && typeof val === 'number') {
displayValue += 'kg';
}
}
$('<span>').addClass('prop-val').text(displayValue).appendTo(line);
props.append(line);
// 如果是加值欄位,在後面也添加一個小分隔線
if (key === '') {
const bottomSeparator = $('<div>').css({
'height': '1px',
'background': 'rgba(148, 197, 255, 0.1)',
'margin': '8px 0 4px 0',
'width': '100%'
});
props.append(bottomSeparator);
}
}
}
});
: 0
itemCard.append(props);
container.append(itemCard);
}
});
}
body.append(container);
}
####
: AI
renderItemCollection('', equipmentSource, true);
renderItemCollection('', itemsSource);
- : 55=60
- : COTAI
if (showCamp && campSource && Object.keys(campSource).length > 0) {
Object.entries(campSource).forEach(([campName, campData]) => {
if (campData && typeof campData === 'object') {
Object.entries(campData).forEach(([categoryKey, categoryData]) => {
if(categoryData && typeof categoryData === 'object' && Object.values(categoryData).some(item => typeof item === 'object')) {
renderItemCollection(`${campName} - ${categoryKey}`, categoryData);
}
});
}
});
}
content.append(weightContainer, body, close);
modal.append(content);
$('body').append(modal);
}
| | |
|------|------------|
| | -10 |
| | -20 |
| | -35 |
| | -50 |
function createStatusEffects(container, data) {
// 使用新的變數路徑 '狀態.生效效果'
const source = data?.['']?.[''];
if (source == null) {
return;
}
: 1d10030
// 新的資料結構:物件,鍵是狀態型別,值包含"狀態"和"效果"
const collected = [];
// 遍歷狀態物件
if (typeof source === 'object' && !Array.isArray(source)) {
Object.values(source).forEach((statusObj) => {
if (statusObj && typeof statusObj === 'object') {
// 提取狀態名稱
const stateName = statusObj[''];
if (stateName) {
// 過濾掉"狀態正常"
if (stateName.trim() === '') {
return;
}
// ✅ 直接使用腳本已經生成的效果描述
const effect = statusObj[''] || '';
collected.push({
name: stateName,
effect: effect
});
}
}
});
} else {
// 處理其他可能的資料結構(備用邏輯)
const collect = (value) => {
if (value == null) return;
if (Array.isArray(value)) {
value.forEach(collect);
return;
}
if (typeof value === 'object') {
Object.values(value).forEach(collect);
return;
}
const text = String(value);
text.split(/[,\s]+/)
.map((item) => item.trim())
.filter(Boolean)
.forEach((item) => {
if (item.trim() === '') return;
collected.push({ name: item, effect: '' });
});
};
collect(e(source, false));
}
: =01
if (collected.length === 0) {
const wrapper = $('<div>').addClass('status-effects-container').css('display', 'none');
container.append(wrapper);
return;
}
:
const wrapper = $('<div>').addClass('status-effects-container');
$('<div>').addClass('section__title').text('').appendTo(wrapper);
const list = $('<div>').addClass('status-effects-list');
collected.forEach((status) => {
const statusContainer = $('<div>').addClass('status-effect-container');
const statusName = $('<div>').addClass('status-effect-name')
.text(status.name)
.attr('title', '');
if (status.effect) {
statusName.addClass('has-effect');
statusName.on('click', function() {
$(this).toggleClass('expanded');
$(this).next('.status-effect-detail').slideToggle(200);
});
const effectDetail = $('<div>').addClass('status-effect-detail')
.hide()
.text(status.effect);
statusContainer.append(statusName, effectDetail);
} else {
statusContainer.append(statusName);
}
list.append(statusContainer);
});
wrapper.append(list);
container.append(wrapper);
}
:
const IMAGE_VIEWER_STORAGE_KEY = 'survivalImageViewerState';
const IMAGE_VIEWER_FALLBACK_URL = 'https://cdn.phototourl.com/free/2026-05-23-8b4cc932-bb3f-4107-9a72-9160fb9e2335.png';
function loadSavedImageViewerState() {
try {
const raw = localStorage.getItem(IMAGE_VIEWER_STORAGE_KEY);
if (!raw) return null;
return JSON.parse(raw);
} catch (error) {
console.error(':', error);
return null;
}
}
####
function persistImageViewerState(state) {
try {
if (!state) localStorage.removeItem(IMAGE_VIEWER_STORAGE_KEY);
else localStorage.setItem(IMAGE_VIEWER_STORAGE_KEY, JSON.stringify(state));
} catch (error) {
console.error(':', error);
}
}
- ActionResult . =
-
- "流產"
- 0
- 0
- +1
-
- 0
- -[]
- -15
- +[]
- 30
-
- 30 ×1.5 CoT AI
let savedImageViewerState = loadSavedImageViewerState();
function resolveMapImageUrl(statData, displayData) {
const candidates = [
statData?.['']?.[''], statData?.['']?.[''], statData?.[''],
statData?.['']?.[''], statData?.['']?.['']?.[''],
displayData?.['']?.[''], displayData?.['']?.[''], displayData?.[''],
];
for (const candidate of candidates) {
const url = textify(candidate, '').trim();
if (url) return url;
}
return IMAGE_VIEWER_FALLBACK_URL || '';
}
### 12.
class ImageViewer {
constructor(root, initialState) {
this.root = root;
this.canvas = root.find('.image-viewer__canvas');
this.image = root.find('.image-viewer__image');
this.placeholder = root.find('.image-viewer__placeholder');
this.status = root.find('.image-viewer__status');
this.controlButtons = root.find('.image-viewer__control-button');
this.scale = initialState?.scale ?? 1;
this.translateX = initialState?.translateX ?? 0;
this.translateY = initialState?.translateY ?? 0;
this.imageUrl = initialState?.url ?? '';
this.imageLoaded = false;
this.activePointers = new Map();
this.initialPinchDistance = 0;
this.minScale = 0.4;
this.maxScale = 4;
this.bindEvents();
if (this.imageUrl) this.loadImage(this.imageUrl, false);
else this.updatePlaceholder(true);
}
bindEvents() {
this.controlButtons.each((_, button) => {
const $button = $(button);
const action = $button.data('action');
if (action === 'zoom-in') $button.on('click.imageViewer', () => this.zoomTo(this.scale * 1.2));
else if (action === 'zoom-out') $button.on('click.imageViewer', () => this.zoomTo(this.scale * 0.8));
else if (action === 'reset') $button.on('click.imageViewer', () => this.resetTransform());
});
const canvasElement = this.canvas[0];
if (canvasElement) canvasElement.addEventListener('wheel', (event) => this.handleWheel(event), { passive: false });
this.canvas
.on('pointerdown.imageViewer', (event) => this.handlePointerDown(event))
.on('pointermove.imageViewer', (event) => this.handlePointerMove(event))
.on('pointerup.imageViewer pointercancel.imageViewer pointerleave.imageViewer', (event) => this.handlePointerUp(event));
}
loadImage(url, resetTransform = true) {
this.setStatus('...');
this.placeholder.hide();
this.imageLoaded = false;
this.image.off('.imageViewer')
.on('load.imageViewer', () => {
this.imageLoaded = true;
this.imageUrl = url;
this.setStatus('');
if (resetTransform) this.resetTransform();
else this.applyTransform();
this.canvas.addClass('has-image');
this.placeholder.hide();
setTimeout(() => this.setStatus(url), 800);
})
.on('error.imageViewer', () => {
this.imageLoaded = false;
this.setStatus('');
this.updatePlaceholder(false, '');
});
this.image.attr('src', url);
}
resetTransform() {
this.scale = 1;
this.translateX = 0;
this.translateY = 0;
this.applyTransform();
}
applyTransform() {
const transform = `translate(-50%, -50%) translate(${this.translateX}px, ${this.translateY}px) scale(${this.scale})`;
this.image.css('transform', transform);
}
zoomTo(newScale, center = null) {
if (!this.imageLoaded) return;
const previousScale = this.scale;
this.scale = Math.min(this.maxScale, Math.max(this.minScale, newScale));
if (center) {
const rect = this.canvas[0]?.getBoundingClientRect();
if (rect) {
const offsetX = center.x - rect.left;
const offsetY = center.y - rect.top;
const scaleRatio = this.scale / previousScale;
this.translateX = (this.translateX + offsetX) - offsetX * scaleRatio;
this.translateY = (this.translateY + offsetY) - offsetY * scaleRatio;
}
}
this.applyTransform();
}
handleWheel(event) {
if (!this.imageLoaded) return;
event.preventDefault();
const delta = event.deltaY > 0 ? 0.9 : 1.1;
this.zoomTo(this.scale * delta, { x: event.clientX, y: event.clientY });
}
handlePointerDown(event) {
if (!this.imageLoaded) return;
this.canvas.addClass('is-grabbing');
this.canvas[0]?.setPointerCapture?.(event.pointerId);
this.activePointers.set(event.pointerId, { x: event.clientX, y: event.clientY });
if (this.activePointers.size === 2) this.initialPinchDistance = this.computePinchDistance();
event.preventDefault();
}
handlePointerMove(event) {
if (!this.activePointers.has(event.pointerId)) return;
const previous = this.activePointers.get(event.pointerId);
const current = { x: event.clientX, y: event.clientY };
this.activePointers.set(event.pointerId, current);
if (this.activePointers.size === 1) {
this.translateX += current.x - previous.x;
this.translateY += current.y - previous.y;
this.applyTransform();
return;
}
> 🔴 / `<crafting_rules>` COT ActionResult
if (this.activePointers.size >= 2) {
const newDistance = this.computePinchDistance();
if (this.initialPinchDistance === 0) {
this.initialPinchDistance = newDistance;
return;
}
const factor = newDistance / this.initialPinchDistance;
this.zoomTo(this.scale * factor, this.computePinchCenter());
this.initialPinchDistance = newDistance;
}
}
handlePointerUp(event) {
this.activePointers.delete(event.pointerId);
if (this.activePointers.size <= 1) this.initialPinchDistance = 0;
if (this.activePointers.size === 0) this.canvas.removeClass('is-grabbing');
}
computePinchDistance() {
const pointers = Array.from(this.activePointers.values());
if (pointers.length < 2) return 0;
return Math.hypot(pointers[0].x - pointers[1].x, pointers[0].y - pointers[1].y) || 0.0001;
}
computePinchCenter() {
const pointers = Array.from(this.activePointers.values());
if (pointers.length < 2) return null;
return { x: (pointers[0].x + pointers[1].x) / 2, y: (pointers[0].y + pointers[1].y) / 2 };
}
updatePlaceholder(show, message = '') {
this.placeholder.toggle(show).text(message || '...');
}
setStatus(message) {
this.status.text(message || '');
}
getState() {
if (!this.imageUrl) return null;
return { url: this.imageUrl, scale: this.scale, translateX: this.translateX, translateY: this.translateY };
}
destroy() {
this.canvas.off('.imageViewer');
this.image.off('.imageViewer');
this.controlButtons.off('.imageViewer');
this.activePointers.clear();
}
}
ActionResult"項目"
function openImageViewerModal(statData, displayData) {
$('.image-viewer-modal').remove();
const modal = $('<div>').addClass('image-viewer-modal');
const content = $('<div>').addClass('image-viewer-modal__content');
const header = $('<div>').addClass('image-viewer__header').append(
$('<div>').addClass('image-viewer__title').text(''),
$('<button>').addClass('image-viewer__close').html('×')
);
const toolbar = $('<div>').addClass('image-viewer__toolbar').append(
$('<div>').addClass('image-viewer__hint').text(''),
$('<div>').addClass('image-viewer__controls').append(
$('<button>').addClass('image-viewer__control-button').data('action', 'zoom-out').text('-'),
$('<button>').addClass('image-viewer__control-button').data('action', 'reset').text(''),
$('<button>').addClass('image-viewer__control-button').data('action', 'zoom-in').text('+')
)
);
const canvas = $('<div>').addClass('image-viewer__canvas').append(
$('<img>').addClass('image-viewer__image').attr({ draggable: 'false', alt: '' }),
$('<div>').addClass('image-viewer__placeholder'),
$('<div>').addClass('image-viewer__status')
);
content.append(header, toolbar, canvas);
modal.append(content);
$('body').append(modal);
const initialState = { ...savedImageViewerState };
const autoUrl = resolveMapImageUrl(statData, displayData);
if (autoUrl) initialState.url = autoUrl;
else if (!initialState.url && IMAGE_VIEWER_FALLBACK_URL) initialState.url = IMAGE_VIEWER_FALLBACK_URL;
const viewer = new ImageViewer(content, initialState);
const closeModal = () => {
viewer.destroy();
savedImageViewerState = viewer.getState();
persistImageViewerState(savedImageViewerState);
modal.remove();
$(document).off('keydown.imageViewer');
};
content.find('.image-viewer__close').on('click', closeModal);
modal.on('click', (e) => e.target === modal[0] && closeModal());
$(document).on('keydown.imageViewer', (e) => e.key === 'Escape' && closeModal());
}
####
function showDrawConfirmModal(drawType, survivalPoints) {
$('.draw-confirm-modal').remove();
const pointName = '';
const safePoints = Number.isFinite(survivalPoints) ? survivalPoints : 0;
const modal = $('<div>').addClass('draw-confirm-modal');
const content = $('<div>').addClass('draw-confirm-modal__content').append(
$('<div>').addClass('draw-confirm-modal__glow'),
$('<div>').addClass('draw-confirm-modal__title').text(''),
$('<div>').addClass('draw-confirm-modal__desc').text(` 100 ${pointName}`),
$('<div>').addClass('draw-confirm-modal__points').html(`${pointName} <span>${safePoints}</span>`),
$('<div>').addClass('draw-confirm-modal__actions'),
$('<div>').addClass('draw-confirm-modal__status')
);
const confirmBtn = $('<button>').addClass('draw-confirm-modal__button draw-confirm-modal__confirm').text('');
const cancelBtn = $('<button>').addClass('draw-confirm-modal__button draw-confirm-modal__cancel').text('');
content.find('.draw-confirm-modal__actions').append(confirmBtn, cancelBtn);
modal.append(content);
$('body').append(modal);
const closeModal = () => modal.remove();
cancelBtn.on('click', closeModal);
modal.on('click', (e) => e.target === modal[0] && closeModal());
$(document).one('keydown', (e) => e.key === 'Escape' && closeModal());
if (safePoints < 100) {
confirmBtn.addClass('is-disabled').prop('disabled', true);
content.find('.draw-confirm-modal__status').text(`${pointName}`);
return;
}
confirmBtn.on('click', async () => {
if (confirmBtn.hasClass('is-loading')) return;
confirmBtn.addClass('is-loading').prop('disabled', true);
try {
const msg = `100${pointName}`;
await triggerSlash(`/send ${msg}`);
content.find('.draw-confirm-modal__status').text('');
setTimeout(closeModal, 900);
} catch (error) {
console.error(':', error);
content.find('.draw-confirm-modal__status').text('');
confirmBtn.removeClass('is-loading').prop('disabled', false);
}
});
}
ActionResult-
- insert `//<>`
- 0 crafting_rules
- `: { '': { '': , '': 0 } }`
-
function renderNutritionDetails(target, statData) {
const wrapper = $('<div>').addClass('nutrition-hydration-wrapper');
const phys = statData[''] ?? {};
const carb = Number(e(phys[''] ?? 0)), fat = Number(e(phys[''] ?? 0)),
protein = Number(e(phys[''] ?? 0)), vitamin = Number(e(phys[''] ?? 0)),
nitrogen = Number(e(phys[''] ?? 0));
wrapper.append(t('', carb, s[''], 'carbs-progress'));
wrapper.append(t('', fat, s[''], 'fat-progress'));
const nitrogenWrapper = $('<div>').addClass('progress-wrapper');
$('<div>').text(`: ${nitrogen}`).appendTo(nitrogenWrapper);
const gradient = $('<div>').addClass('nitrogen-gradient');
$('<div>').addClass('nitrogen-marker').css('left', `${((Math.max(-100, Math.min(100, nitrogen)) + 100) / 200) * 100}%`).appendTo(gradient);
wrapper.append(nitrogenWrapper.append(gradient));
wrapper.append(t('', protein, s[''], 'protein-progress'));
wrapper.append(t('', vitamin, s[''], 'vitamin-progress'));
target.append(wrapper);
}
####
function renderPhysMental(target, physData, mentalData, fullData) {
const wrapper = $('<div>').addClass('phys-mental-wrapper');
const physCol = $('<div>').addClass('phys-col').append($('<div>').addClass('section__title').text(''));
const mentalCol = $('<div>').addClass('mental-col').append($('<div>').addClass('section__title').text(''));
const temperature = Number(e(physData[''] ?? 37));
const tempWrapper = $('<div>').addClass('progress-wrapper').append($('<div>').text(`: ${temperature}°C (36.5-37.5)`));
const tempGradient = $('<div>').addClass('temp-gradient');
$('<div>').addClass('temp-marker').css('left', `${Math.min(Math.max(((temperature - 35) / 5) * 100, 0), 100)}%`).appendTo(tempGradient);
$('<div>').addClass('temp-normal-zone').css({ left: '30%', width: '20%' }).appendTo(tempGradient);
physCol.append(tempWrapper.append(tempGradient));
physCol.append(t('', Number(e(fullData['']?.[''] ?? 0)), (Number(e(fullData['']?.['']?.[''] ?? 25)) || 25) * 4, 'fatigue-progress'));
const immuneLoad = Number(e(physData[''] ?? 0)), immunePower = Number(e(fullData['']?.[''] ?? 0));
const immuneWrapper = $('<div>').addClass('progress-wrapper').append($('<div>').text(`: ${immuneLoad} / ${immunePower}`));
const immuneBar = $('<div>').addClass('immune-bar');
$('<div>').addClass('immune-fill').css('width', `${Math.min(immuneLoad, 100)}%`).appendTo(immuneBar);
$('<div>').addClass('immune-marker').css('left', `${Math.min(immunePower, 100)}%`).appendTo(immuneBar);
physCol.append(immuneWrapper.append(immuneBar));
Object.entries(mentalData).forEach(([key, value]) => mentalCol.append(t(key, Number(e(value)), s[key] ?? 100)));
wrapper.append(physCol, mentalCol);
target.append(wrapper);
}
ActionResult-
- crafting_rules
- = ( / ) × 100
- replace `//<>/`
- replace `//<>//<>/`
- remove replace
- replace `//<>/`
- `` ``
- replace `//<>/`
function renderAttributesAndSkills(target, attributesSource, skillsSource, talentsSource, companionDetails = null) {
// ============== 參數保護 ==============
attributesSource = attributesSource || {};
skillsSource = skillsSource || {};
talentsSource = talentsSource || {};
// 確保 companionDetails 是物件(如果不是就設為空物件)
if (companionDetails === null || typeof companionDetails !== 'object') {
companionDetails = {};
}
const wrapper = $('<div>').addClass('attr-skill-wrapper');
const leftCol = $('<div>').addClass('attr-col');
// ============== 屬性渲染 ==============
$('<div>').addClass('section__title').text('').appendTo(leftCol);
// 安全地獲取屬性物件
const attributes = firstMeaningfulObject(attributesSource);
if (Object.keys(attributes).length > 0) {
Object.entries(attributes).forEach(([name, detail]) => {
if (detail && typeof detail === 'object') {
const level = Number(e(detail[''] ?? 0));
const exp = Number(e(detail[''] ?? 0));
const required = Number(e(detail[''] ?? 1)) || 1;
leftCol.append($('<div>').text(`${name} Lv.${level}`), t('', exp, required));
}
});
} else {
leftCol.append($('<p>').addClass('empty-text').text(''));
}
// ============== 天賦渲染 ==============
const talentEntries = toEntries(talentsSource);
if (talentEntries.length > 0) {
leftCol.append($('<div>').addClass('section__title').css('margin-top', '20px').text('/'));
talentEntries.forEach(([name, value]) => {
const item = $('<div>').addClass('skill-item');
// 天賦名稱(安全處理)
let talentName = name;
if (value && typeof value === 'object' && value.name) {
talentName = value.name;
}
$('<div>').addClass('skill-name').text(talentName).appendTo(item);
if (value && typeof value === 'object') {
// 先顯示描述
if (value['']) {
$('<div>').addClass('skill-desc').text(textify(value[''], '')).appendTo(item);
}
// 顯示其他非描述、非加值的內容
Object.entries(value).forEach(([key, val]) => {
if (key !== '$meta' && key !== 'name' && key !== '' && key !== '') {
$('<div>').addClass('skill-desc').text(`${key}${textify(val, '')}`).appendTo(item);
}
});
// 顯示加值(如果有)
if (value[''] && typeof value[''] === 'object') {
const bonusEntries = [];
Object.entries(value['']).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
// 如果有其他內容,添加分隔線
const hasOtherContent = value[''] || Object.keys(value).some(k =>
k !== '$meta' && k !== 'name' && k !== '' && k !== ''
);
if (hasOtherContent) {
const separator = $('<div>').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '8px 0',
'width': '100%'
});
item.append(separator);
}
// 加值顯示
const bonusDiv = $('<div>').addClass('skill-desc talent-bonus').css({
'background': 'rgba(94, 161, 255, 0.08)',
'border-left': '3px solid var(--survival-accent)',
'padding': '6px 10px',
'border-radius': '4px',
'margin': '4px 0'
}).text(`${bonusEntries.join('')}`);
item.append(bonusDiv);
}
} else if (typeof value === 'string') {
$('<div>').addClass('skill-desc').text(value).appendTo(item);
}
leftCol.append(item);
});
}
// ============== 專屬特色渲染(新增安全檢查) ==============
if (companionDetails && typeof companionDetails === 'object') {
// 安全地獲取專屬特色
const exclusiveTraits = companionDetails[''];
if (exclusiveTraits && typeof exclusiveTraits === 'object' && Object.keys(exclusiveTraits).length > 0) {
leftCol.append($('<div>').addClass('section__title').css('margin-top', '20px').text(''));
Object.entries(exclusiveTraits).forEach(([name, desc]) => {
if (name && desc) { // 確保名稱和描述都存在
const item = $('<div>').addClass('skill-item');
$('<div>').addClass('skill-name').text(name).appendTo(item);
// 處理描述可能是物件或字串
let description = '';
if (typeof desc === 'object' && desc['']) {
description = desc[''];
} else if (typeof desc === 'string') {
description = desc;
} else {
description = textify(desc, '');
}
$('<div>').addClass('skill-desc').text(description).appendTo(item);
leftCol.append(item);
}
});
}
}
// ============== 右側技能欄 ==============
const rightCol = $('<div>').addClass('skill-col');
$('<div>').addClass('section__title').text('').appendTo(rightCol);
const skillEntries = toEntries(skillsSource);
if (skillEntries.length === 0) {
rightCol.append($('<p>').addClass('empty-text').text(''));
} else {
skillEntries.forEach(([name, value]) => {
if (value && typeof value === 'object') {
const level = Number(e(value[''] ?? 0));
const exp = Number(e(value[''] ?? 0));
const required = Number(e(value[''] ?? 1)) || 1;
const item = $('<div>').addClass('skill-item');
$('<div>').addClass('skill-name').text(`${name} Lv.${level}`).appendTo(item);
item.append(t('', exp, required));
rightCol.append(item);
} else if (typeof value === 'string' || typeof value === 'number') {
// 處理簡單類型的技能
const item = $('<div>').addClass('skill-item');
$('<div>').addClass('skill-name').text(name).appendTo(item);
$('<div>').addClass('skill-desc').text(textify(value, '')).appendTo(item);
rightCol.append(item);
}
});
}
wrapper.append(leftCol, rightCol);
target.append(wrapper);
}
####
function renderUnifiedStatus(target, statData) {
const wrapper = $('<div>').addClass('phys-mental-wrapper');
const leftCol = $('<div>').addClass('phys-col');
const rightCol = $('<div>').addClass('mental-col');
const phys = statData[''] ?? {};
const mental = statData[''] ?? {};
const state = statData[''] ?? {};
$('<div>').addClass('section__title').text('').appendTo(leftCol);
const currentWeight = Number(e(state[''] ?? 0)), maxWeight = Number(e(state[''] ?? 0));
leftCol.append(t(`: ${currentWeight.toFixed(1)}/${maxWeight.toFixed(1)} kg`, currentWeight, maxWeight, 'weight-progress'));
// ✅ 修改這裡:從 phys 讀取飽腹感
leftCol.append(t('', Number(e(phys[''] ?? 0)), 100, 'hunger-progress'));
leftCol.append(t('', Number(e(phys[''] ?? 0)), 100, 'water-progress'));
leftCol.append(t('', Number(e(phys[''] ?? 0)), s[''], 'protein-progress'));
leftCol.append(t('', Number(e(phys[''] ?? 0)), 100, 'vitamin-progress'));
leftCol.append(t('', Number(e(phys[''] ?? 0)), s[''], 'carbs-progress'));
leftCol.append(t('', Number(e(phys[''] ?? 0)), s[''], 'fat-progress'));
const immuneLoad = Number(e(phys[''] ?? 0)), immunePower = Number(e(state[''] ?? 0));
const immuneWrapper = $('<div>').addClass('progress-wrapper').append($('<div>').text(`: ${immuneLoad} / ${immunePower}`));
const immuneBar = $('<div>').addClass('immune-bar');
$('<div>').addClass('immune-fill').css('width', `${Math.min(immuneLoad, 100)}%`).appendTo(immuneBar);
$('<div>').addClass('immune-marker').css('left', `${Math.min(immunePower, 100)}%`).appendTo(immuneBar);
leftCol.append(immuneWrapper.append(immuneBar));
const nitrogen = Number(e(phys[''] ?? 0));
const nitrogenWrapper = $('<div>').addClass('progress-wrapper nitrogen-balance').append($('<div>').text(`: ${nitrogen}`));
const gradient = $('<div>').addClass('nitrogen-gradient');
$('<div>').addClass('nitrogen-marker').css('left', `${((Math.max(-100, Math.min(100, nitrogen)) + 100) / 200) * 100}%`).appendTo(gradient);
leftCol.append(nitrogenWrapper.append(gradient));
$('<div>').addClass('section__title').text('').appendTo(rightCol);
rightCol.append(t('', Number(e(mental[''] ?? 0)), 100));
rightCol.append(t('', Number(e(mental[''] ?? 0)), 100));
rightCol.append(t('', Number(e(mental[''] ?? 0)), 100));
rightCol.append(t('', Number(e(mental[''] ?? 0)), 100));
rightCol.append(t('', Number(e(mental[''] ?? 0)), 100));
rightCol.append(t('', Number(e(state[''] ?? 0)), 100));
rightCol.append(t('', Number(e(state[''] ?? 0)), 100));
rightCol.append(t('', Number(e(state[''] ?? 0)), 100));
rightCol.append(t('', Number(e(state[''] ?? 0)), 100, 'danger-progress'));
rightCol.append(t('', Number(e(state[''] ?? 0)), 100, 'warning-progress'));
function renderKV(target, data, title) {
if (!data || Object.keys(data).length === 0) return;
if (title) $('<div>').addClass('section__title').text(title).appendTo(target);
const list = $('<ul>').addClass('section__list');
Object.entries(data).forEach(([key, value]) => {
$('<li>').addClass('item').append($('<span>').addClass('item__key').text(key), $('<span>').addClass('item__value').text(textify(value, '--'))).appendTo(list);
});
target.append(list);
}
renderKV(rightCol, {'': textify(state[''], ''), '': textify(state[''], ''), '': textify(state[''], '')});
wrapper.append(leftCol, rightCol);
target.append(wrapper);
}
ActionResult-
- crafting_rules 50 / 70 / 90
-
- remove `//<>`
- insert insert
-
-
-
-
-
-
-
function renderTemperatures(container, data) { const environment = data[''] ?? {}, phys = data[''] ?? {};
const tempWrapper = $('<div>').addClass('temp-range-wrapper');
const coreTemp = Number(e(phys[''] ?? 37)), minNormal = 36.5, maxNormal = 37.5;
const coreTempSubWrapper = $('<div>').css('margin-bottom', '8px').append($('<div>').text(`: ${coreTemp.toFixed(1)}°C (: ${minNormal}-${maxNormal})`));
const coreTempBar = $('<div>').addClass('temp-range-bar');
const coreRangeMin = 35, coreRangeSpan = 7;
const coreCurrentPercent = Math.max(0, Math.min(100, ((coreTemp - coreRangeMin) / coreRangeSpan) * 100));
const coreNormalStart = ((minNormal - coreRangeMin) / coreRangeSpan) * 100;
const coreNormalWidth = ((maxNormal - minNormal) / coreRangeSpan) * 100;
coreTempBar.append(
$('<div>').addClass('temp-gradient'),
$('<div>').addClass('comfort-zone').css({ left: `${coreNormalStart}%`, width: `${coreNormalWidth}%` }),
$('<div>').addClass('current-temp').css('left', `${coreCurrentPercent}%`)
);
tempWrapper.append(coreTempSubWrapper.append(coreTempBar));
const feltTemp = Number(e(environment[''] ?? 20)), minComfort = Number(e(data['']?.[''] ?? 15)), maxComfort = Number(e(data['']?.[''] ?? 25));
const feltTempSubWrapper = $('<div>').append($('<div>').text(`: ${feltTemp}°C (: ${minComfort}-${maxComfort})`));
const feltTempBar = $('<div>').addClass('temp-range-bar');
const feltRangeMin = 0, feltRangeSpan = 50;
const feltCurrentPercent = Math.max(0, Math.min(100, ((feltTemp - feltRangeMin) / feltRangeSpan) * 100));
const feltComfortStart = ((minComfort - feltRangeMin) / feltRangeSpan) * 100;
const feltComfortWidth = ((maxComfort - minComfort) / feltRangeSpan) * 100;
feltTempBar.append(
$('<div>').addClass('temp-gradient'),
$('<div>').addClass('comfort-zone').css({ left: `${feltComfortStart}%`, width: `${feltComfortWidth}%` }),
$('<div>').addClass('current-temp').css('left', `${feltCurrentPercent}%`)
);
tempWrapper.append(feltTempSubWrapper.append(feltTempBar));
container.append(tempWrapper);
}
####
function r(container, data) {
const environment = data[''] ?? {}, system = data[''] ?? {};
const phys = data[''] ?? {};
const mental = data[''] ?? {};
const state = data[''] ?? {};
const top = $('<div>').addClass('top-info');
top.append($('<div>').addClass('time-display').text(textify(system[''], '--:--')));
const infoStack = $('<div>').addClass('info-stack');
infoStack.append(
$('<div>').addClass('info-row').append(
$('<div>').addClass('row-item').text(`Day ${e(system[''] ?? 0)}`),
$('<div>').addClass('row-item').text(textify(environment[''], '')),
$('<div>').addClass('row-item').text(textify(environment[''], ''))
),
$('<div>').addClass('info-row').append(
$('<div>').addClass('row-item').text(textify(environment[''], '')),
$('<div>').addClass('row-item').text(` ${textify(environment[''], '--')}`),
$('<div>').addClass('row-item').text(` ${textify(environment[''], '--')}`)
),
$('<div>').addClass('info-row').append(
$('<div>').addClass('row-item').text(`${textify(system[''], '🔄 ')}`)
)
);
top.append(infoStack, $('<div>').addClass('location-display').text(`${textify(environment[''], '')}`));
container.append(top);
renderTemperatures(container, data);
const hpCurrent = Number(e(phys[''] ?? 0)), hpMax = Number(e(phys[''] ?? 0));
const mpCurrent = Number(e(mental[''] ?? 0)), mpMax = Number(e(mental[''] ?? 0));
const coreWrapper = $('<div>').addClass('core-stats-wrapper');
coreWrapper.append($('<div>').addClass('core-stat-item').append(t('', hpCurrent, hpMax, 'hp-progress')));
coreWrapper.append($('<div>').addClass('core-stat-item').append(t('', mpCurrent, mpMax, 'mp-progress')));
container.append(coreWrapper);
}
-
-
-
- JSON Patch
function renderKeyValueTree(target, data) {
const entries = toEntries(data);
if (!entries || entries.length === 0) return;
const list = $('<ul>').addClass('section__list');
entries.forEach(([key, value]) => {
const li = $('<li>');
if (value && typeof value === 'object') {
$('<div>').addClass('item').append($('<span>').addClass('item__key').text(String(key))).appendTo(li);
renderKeyValueTree(li, value);
} else {
$('<div>').addClass('item').append($('<span>').addClass('item__key').text(String(key)), $('<span>').addClass('item__value').text(textify(value, ''))).appendTo(li);
}
list.append(li);
});
target.append(list);
}
### 13.
function renderTaskSystem(container, data) {
const tasksData = data[''] ?? {};
const { $section, $body } = d('', true);
const getStatusClass = (status) => ({'':'status-ongoing', '':'status-pending', '':'status-completed', '':'status-failed', '':'status-abandoned'}[status] || 'status-ongoing');
const getStatusText = (status) => ({'':'', '':'', '':'', '':'', '':''}[status] || '');
const renderRewards = (rewardsData) => {
if (!rewardsData) return '';
if (typeof rewardsData === 'string') {
return '<span class="points">' + rewardsData + '</span>';
}
if (typeof rewardsData === 'object') {
const parts = [];
Object.entries(rewardsData).forEach(([key, value]) => {
if (key === '') {
parts.push('<span class="points">' + value + '</span>');
} else if (key === '') {
parts.push('<span class="points">' + value.replace('', '').replace('', '') + '</span>');
} else if (typeof value === 'object') {
const subParts = Object.entries(value).map(function(sub) {
return sub[0] + ' +' + sub[1] + ' exp';
});
parts.push('<span class="points">' + key + '' + subParts.join(', ') + '</span>');
} else {
parts.push('<span class="points">' + key + ' +' + value + '</span>');
}
});
return parts.join(', ');
}
return '';
};
const createTaskDetail = (task, type, data) => {
const detail = $('<div>').addClass('task-detail').hide();
const colorMap = {'':'#3498db', '':'#f39c12', '':'#2ecc71', '':'#e74c3c', '':'#8E44AD'};
if (task['']) detail.append($('<div>').css({'font-size':'18px', 'font-weight':'bold', 'text-align':'center', 'margin-bottom':'8px', 'padding':'4px 0', 'color':colorMap[type] || '#fff'}).text(task['']));
detail.append($('<div>').addClass('task-divider'));
// 任務描述
if (task['']) detail.append($('<div>').addClass('task-desc').text(task[''] || ''));
if (task['']) detail.append($('<div>').addClass('target-desc').html(`: <span style="color:var(--survival-warning); font-weight:bold;">${task['']}</span>`));
// 任務時間顯示
if (task['']) {
const currentDay = Number(e(data?.['']?.[''] ?? 0));
const currentTime = textify(data?.['']?.[''] ?? '00:00');
const currentTimeString = `${currentDay} ${currentTime}`;
const totalCurrentMinutes = parseTimeToMinutes(currentTimeString);
const totalEndMinutes = parseTimeToMinutes(task['']);
if (totalCurrentMinutes !== null && totalEndMinutes !== null) {
const remainingMinutes = totalEndMinutes - totalCurrentMinutes;
const remainingTimeText = formatRemainingTime(remainingMinutes);
let timeColor = 'var(--survival-text)';
if (remainingMinutes <= 0) timeColor = 'var(--survival-danger)';
else if (remainingMinutes < 6 * 60) timeColor = 'var(--survival-warning)';
const timeContainer = $('<div>').addClass('target-desc').css('display', 'flex', 'align-items', 'center', 'gap', '8px');
timeContainer.append($('<span>').css('color', timeColor).text(''));
timeContainer.append($('<span>').css('color', 'var(--survival-warning)').css('font-weight', 'bold').text(remainingTimeText));
detail.append(timeContainer);
} else {
detail.append($('<div>').addClass('target-desc').html(`: <span style="color:var(--survival-warning); font-weight:bold;">${task['']}</span>`));
}
}
// 緊急任務特殊處理
if (type === '') {
const emergencyInfo = $('<div>').addClass('time-info').css('text-align', 'left');
if (task['']) emergencyInfo.append($('<div>').html(`: <span style="color:var(--survival-warning); font-weight:bold;">${task['']}</span>`));
if (task['']) emergencyInfo.append($('<div>').addClass('penalty-info').html(`: ${task['']}`));
detail.append(emergencyInfo);
}
detail.append($('<div>').addClass('task-divider'));
// ========== 主要要求(基礎要求) ==========
if (task[''] && typeof task[''] === 'object') {
const requirementSection = $('<div>').addClass('target-section').append($('<div>').addClass('section-title').text(''));
// 處理基礎要求(可能是陣列或物件)
const requirements = task[''];
Object.entries(requirements).forEach(([reqKey, reqData]) => {
// 跳過進階目標(因為進階目標會另外處理)
if (reqKey === '') return;
if (reqData && typeof reqData === 'object') {
const desc = $('<div>').addClass('target-desc');
const current = Number(e(reqData[''])) || 0;
const target = Number(e(reqData[''])) || 1;
const reqType = reqData[''] || '';
// 獲取描述文字
let descriptionText = reqData[''] || '';
if (!descriptionText && reqKey) {
descriptionText = reqKey.replace(/^\d*/, '');
}
desc.append($('<span>').text(descriptionText));
if (reqType === '') {
desc.append($('<span>').addClass('progress-number').text(` (${current}/${target})`));
}
if (current >= target) desc.addClass('completed');
requirementSection.append(desc);
}
});
if (task['']) {
requirementSection.append($('<div>').addClass('reward-info').html(`: ${renderRewards(task[''])}`));
}
detail.append(requirementSection);
}
ActionResult"研究"
// ========== 進階目標(修正版:正確顯示描述) ==========
if (type !== '' && task[''] && Object.keys(task['']).length > 0) {
detail.append($('<div>').addClass('task-divider'));
const bonusSection = $('<div>').addClass('target-section').append($('<div>').addClass('section-title').text(''));
// 正確遍歷進階目標
Object.entries(task['']).forEach(([goalKey, goalData]) => {
if (goalData && typeof goalData === 'object') {
const desc = $('<div>').addClass('target-desc');
const current = Number(e(goalData[''])) || 0;
const target = Number(e(goalData[''])) || 1;
const goalType = goalData[''] || '';
// 獲取描述文字(優先使用 goalData['描述']
let descriptionText = '';
if (goalData['']) {
descriptionText = goalData[''];
} else if (goalKey) {
// 如果沒有描述,使用 key 名稱
descriptionText = goalKey.replace(/^\d*/, '');
}
desc.append($('<span>').text(descriptionText));
if (goalType === '') {
desc.append($('<span>').addClass('progress-number').text(` (${current}/${target})`));
}
if (current >= target) desc.addClass('completed');
bonusSection.append(desc);
}
});
if (task['']) {
bonusSection.append($('<div>').addClass('reward-info').html(`: ${renderRewards(task[''])}`));
}
detail.append(bonusSection);
}
return detail;
};
let hasTasks = false;
// ========== 世界任務(終極任務,特殊顯示) ==========
const worldTask = tasksData[''];
if (worldTask && typeof worldTask === 'object' && worldTask['']) {
hasTasks = true;
// 終極任務專屬樣式 - 金色發光邊框 + 特殊動畫
const strip = $('<div>').addClass('task-strip world-task');
strip.append($('<div>').addClass('task-content').html('🌍 🌍'));
// 狀態指示器
const status = worldTask[''] || '';
const indicator = $('<div>').addClass('task-status-indicator');
indicator.append($('<div>').addClass('status-text').addClass(getStatusClass(status)).text(getStatusText(status)));
strip.append(indicator);
// 任務詳情
const detail = createTaskDetail(worldTask, '', data);
// 點擊展開/收合
strip.on('click', () => {
$('.task-detail').not(detail).slideUp();
detail.slideToggle();
});
$body.append(strip, detail);
}
['', '', '', '', ''].forEach(key => {
const task = tasksData[key];
if (task && typeof task === 'object' && task['']) {
hasTasks = true;
const keyNameMapping = {'': '', '': '', '': '', '': '', '': ''};
const classNameMapping = {'': 'main-task', '': 'side-task', '': 'daily-task', '': 'emergency-task', '': 'bond-task'};
const status = task[''] || '';
const strip = $('<div>').addClass('task-strip').addClass(classNameMapping[key]);
strip.append($('<div>').addClass('task-content').text(keyNameMapping[key]));
const indicator = $('<div>').addClass('task-status-indicator');
indicator.append($('<div>').addClass('status-text').addClass(getStatusClass(status)).text(getStatusText(status)));
strip.append(indicator);
const detail = createTaskDetail(task, keyNameMapping[key], data);
strip.on('click', () => { $('.task-detail').not(detail).slideUp(); detail.slideToggle(); });
$body.append(strip, detail);
}
});
const bondTasks = tasksData[''];
if (bondTasks && typeof bondTasks === 'object' && Object.keys(bondTasks).length > 0) {
hasTasks = true;
Object.entries(bondTasks).forEach(([companionName, task]) => {
if (task && typeof task === 'object' && task['']) {
const status = task[''] || '';
const strip = $('<div>').addClass('task-strip bond-task');
strip.append($('<div>').addClass('task-content').text(` - ${companionName}`));
const indicator = $('<div>').addClass('task-status-indicator');
indicator.append($('<div>').addClass('status-text').addClass(getStatusClass(status)).text(getStatusText(status)));
strip.append(indicator);
const detail = createTaskDetail(task, '', data);
strip.on('click', () => { $('.task-detail').not(detail).slideUp(); detail.slideToggle(); });
$body.append(strip, detail);
}
});
}
if (!hasTasks) {
$body.append($('<div>').addClass('empty-text').text(''));
}
container.append($section);
}
####
function renderCompanions(container, companionsSource) {
if (companionsSource == null || Object.keys(companionsSource).length === 0) return;
const { $section, $body } = d('', false);
const companionEntries = toEntries(companionsSource);
if (companionEntries.length === 0) {
$body.append($('<p>').addClass('empty-text').text(''));
} else {
companionEntries.forEach(([name, details]) => {
if (details && typeof details === 'object') {
const card = $('<div>').addClass('collapsible').css('margin-bottom', '10px');
const cardHeader = $('<div>').addClass('collapsible__header').text(name);
const cardBody = $('<div>').addClass('collapsible__body');
// 🔧 修改的地方:安全获取当前状态(支持新的数据结构)
const currentState = details?.['']?.[''] ?? details?.[''];
const healthStatus = textify(currentState, '');
const healthValue = Number(e(details[''] ?? 100));
let statusColor = '#2ecc71';
if (healthValue <= 0) statusColor = '#7f8c8d';
else if (healthValue < 10) statusColor = '#8e44ad';
else if (healthValue < 30) statusColor = '#e74c3c';
else if (healthValue < 50) statusColor = '#e67e22';
else if (healthValue < 70) statusColor = '#f39c12';
const statusRow = $('<div>').css({'font-size': '16px', 'font-weight': 'bold', 'color': 'var(--survival-warning)', 'margin-top': '14px', 'margin-bottom': '10px', 'text-align': 'left'});
$('<span>').text(': ').appendTo(statusRow);
$('<span>').css('color', statusColor).text(healthStatus).appendTo(statusRow);
cardBody.append(statusRow);
const statusWrapper = $('<div>').addClass('phys-mental-wrapper').css('margin-bottom', '20px');
const physCol = $('<div>').addClass('phys-col');
const mentalCol = $('<div>').addClass('mental-col');
$('<div>').addClass('section__title').text('').appendTo(physCol);
const health = Math.min(Number(e(details[''] ?? 0)), 100);
const water = Math.min(Number(e(details[''] ?? 0)), 100);
const satiety = Math.min(Number(e(details[''] ?? 0)), 100);
const fatigue = Math.min(Number(e(details[''] ?? 0)), 100);
physCol.append(t(`: ${health}/100 (${getHealthStatus(health)})`, health, 100, 'health-progress'));
physCol.append(t(`: ${water}/100`, water, 100, 'water-progress'));
physCol.append(t(`: ${satiety}/100`, satiety, 100, 'satiety-progress'));
physCol.append(t(`: ${fatigue}/100`, fatigue, 100, 'fatigue-progress'));
/*$('<div>').addClass('section__title').text('').appendTo(mentalCol);
const love = Math.min(Number(e(details[''] ?? 0)), 120);
const desire = Math.min(Number(e(details[''] ?? 0)), 100);
const dev = Math.min(Number(e(details[''] ?? 0)), 100);
const crevice = Math.min(Number(e(details[''] ?? 0)), 100);
mentalCol.append(t(`: ${love.toFixed(1)}/100 (${getFavorabilityStatus(love)})`, love, 100, 'love-progress'));
mentalCol.append(t(`: ${desire.toFixed(1)}/100 (${getDesireStatus(desire)})`, desire, 100, 'desire-progress'));
mentalCol.append(t(`: ${dev.toFixed(1)}/100`, dev, 100, 'dev-progress'));
mentalCol.append(t(`: ${crevice.toFixed(1)}/100 (${getCreviceStatus(crevice)})`, crevice, 100, 'crevice-progress'));
statusWrapper.append(physCol, mentalCol);
cardBody.append(statusWrapper);*/
// ================ 移動:先渲染屬性與技能 ================
renderAttributesAndSkills(cardBody, details[''], details[''], details[''], details);
// ================ 移動:裝備顯示在攜帶物品上面 ================
const equipment = details[''] ?? {};
// 檢查是否有任何裝備
let hasAnyEquipment = false;
const equipmentSlots = [
'', '', '', '', '',
'', '', '', '', ''
];
// 先檢查哪些部位有裝備
const occupiedSlots = equipmentSlots.filter(slot => {
const equipmentItem = equipment[slot];
return equipmentItem && typeof equipmentItem === 'object' && Object.keys(equipmentItem).length > 0;
});
// 如果有任何裝備才顯示裝備欄位
if (occupiedSlots.length > 0) {
// 注意:這裡沒有 margin-top,因為它緊接在屬性技能後面
cardBody.append($('<div>').addClass('section__title').text(''));
// 使用跟玩家完全一樣的裝備網格
const equipmentGrid = $('<div>').addClass('inventory-grid equipment-grid').css({
'grid-template-columns': 'repeat(5, 1fr)', // 一行5個
'gap': '15px'
});
// 只顯示有裝備的部位
occupiedSlots.forEach((slot, index) => {
const slotContainer = $('<div>').addClass('equipment-slot')
.attr('data-slot', slot)
.css({
'background': 'var(--survival-surface-strong)',
'border': '1px solid var(--survival-glass-border)',
'border-radius': '12px',
'padding': '16px',
'text-align': 'center',
'transition': 'all 0.25s ease-out',
'min-height': '140px',
'display': 'flex',
'flex-direction': 'column',
'justify-content': 'flex-start'
});
// 裝備部位標題(跟玩家一樣)
const slotTitle = $('<div>').addClass('slot-title').css({
'font-size': '20px',
'font-weight': '700',
'color': '#d17d2e',
'letter-spacing': '0.05em',
'text-transform': 'uppercase',
'margin-bottom': '12px',
'padding-bottom': '8px',
'border-bottom': '1px solid rgba(148, 197, 255, 0.2)',
'line-height': '1.2'
}).text(slot);
slotContainer.append(slotTitle);
// 獲取該部位的裝備
const equipmentItem = equipment[slot];
// 獲取裝備名稱(第一個鍵名)
const itemKey = Object.keys(equipmentItem)[0];
const itemData = equipmentItem[itemKey];
if (itemKey && itemData) {
const itemNameDiv = $('<div>').addClass('equipment-item-name').css({
'font-size': '18px',
'font-weight': '600',
'color': 'var(--survival-accent-strong)',
'margin-bottom': '8px',
'word-wrap': 'break-word',
'line-height': '1.3',
'padding': '8px 10px',
'background': 'rgba(94, 161, 255, 0.1)',
'border': '1px solid rgba(94, 161, 255, 0.2)',
'border-radius': '6px',
'width': '100%',
'text-align': 'center'
}).text(itemKey);
slotContainer.append(itemNameDiv);
// 顯示裝備屬性(跟玩家完全一樣的邏輯)
const itemProps = $('<div>').addClass('equipment-item-props').css({
'font-size': '12px',
'color': 'var(--survival-text)',
'opacity': '0.8',
'text-align': 'left',
'line-height': '1.4',
'margin-top': '10px',
'padding': '8px',
'background': 'rgba(20, 30, 50, 0.5)',
'border-radius': '6px',
'border': '1px solid rgba(94, 161, 255, 0.1)',
'width': '100%'
});
// 完整的屬性顯示邏輯(跟玩家一樣)
const orderedProps = ['', '', '', ''];
const attributes = new Map();
// 先按照順序處理
orderedProps.forEach(k => {
if (itemData.hasOwnProperty(k)) {
attributes.set(k, itemData[k]);
}
});
// 處理狀態類型和狀態
const stateType = textify(itemData[''] ?? '', '');
if (stateType && itemData.hasOwnProperty('')) {
// 如果狀態類型不是'耐久度',或者還沒有設置耐久度,則添加
if (stateType.toLowerCase() !== '' || !attributes.has('')) {
attributes.set(stateType, itemData['']);
}
}
// 處理其他屬性(跟玩家一樣顯示所有屬性)
// 處理其他屬性(跟玩家一樣顯示所有屬性)
Object.entries(itemData).forEach(([k, v]) => {
if (!attributes.has(k) && k !== '$meta' && k !== '' && k !== '') {
// 特別處理加值欄位
if (k === '' && v && typeof v === 'object') {
const bonusEntries = [];
Object.entries(v).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
attributes.set(k, bonusEntries.join(''));
} else {
attributes.set(k, v);
}
}
});
// 顯示所有屬性(使用跟玩家一樣的樣式)
attributes.forEach((v, k) => {
if (v !== null && v !== '' && v !== undefined) {
const line = $('<div>').addClass('equipment-prop');
line.attr('data-prop', k);
// 如果是加值欄位,添加特殊類別
if (k === '') {
line.addClass('bonus-prop');
// 在加值前面添加分隔線
const separator = $('<div>').addClass('bonus-separator').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '10px 0 8px 0',
'width': '100%'
});
itemProps.append(separator);
}
let displayValue = textify(v, '');
if (k === '' && typeof v === 'number') {
displayValue += 'kg';
}
// 如果是數量,確保顯示
if (k === '') {
displayValue = String(displayValue);
}
// 限制描述長度
if (k === '' && displayValue.length > 80) {
displayValue = displayValue.substring(0, 77) + '...';
}
$('<span>').addClass('prop-key').text(String(k)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
$('<span>').addClass('prop-val').text(displayValue).appendTo(line);
itemProps.append(line);
// 如果是加值欄位,在後面也添加一個小分隔線
if (k === '') {
const bottomSeparator = $('<div>').css({
'height': '1px',
'background': 'rgba(148, 197, 255, 0.1)',
'margin': '8px 0 4px 0',
'width': '100%'
});
itemProps.append(bottomSeparator);
}
}
});
if (attributes.size > 0) {
slotContainer.append(itemProps);
}
// 懸停效果(跟玩家一樣)
slotContainer.hover(
function() {
$(this).css({
'transform': 'translateY(-3px)',
'box-shadow': '0 8px 25px rgba(0,0,0,0.3), 0 0 20px rgba(94, 161, 255, 0.15)',
'background': 'rgba(40, 55, 85, 0.9)',
'border-color': 'var(--survival-accent)'
});
},
function() {
$(this).css({
'transform': 'translateY(0)',
'box-shadow': 'none',
'background': 'var(--survival-surface-strong)',
'border-color': 'var(--survival-glass-border)'
});
}
);
}
equipmentGrid.append(slotContainer);
});
// 根據有裝備的部位數量調整網格布局
const slotCount = occupiedSlots.length;
if (slotCount <= 5) {
equipmentGrid.css('grid-template-columns', `repeat(${slotCount}, 1fr)`);
} else if (slotCount <= 10) {
equipmentGrid.css('grid-template-columns', 'repeat(5, 1fr)');
}
cardBody.append(equipmentGrid);
}
// ================ 完整的同伴裝備欄位結束 ================
// ================ 移動:攜帶物品顯示在最下面 ================
cardBody.append($('<div>').addClass('section__title').css('margin-top', '20px').text(''));
const inventoryContainer = $('<div>').addClass('companion-inventory-grid');
const items = details[''] ? firstMeaningfulObject(details['']) : {};
const itemEntries = Object.entries(items);
if (itemEntries.length === 0) {
inventoryContainer.append($('<p>').addClass('empty-text').css('grid-column', '1 / -1').text(''));
} else {
itemEntries.forEach(([itemName, itemDetails]) => {
const itemCard = $('<div>').addClass('inventory-item');
$('<div>').addClass('item-name').text(itemName).appendTo(itemCard);
if (itemDetails && typeof itemDetails === 'object') {
const props = $('<div>').addClass('item-props');
const attributes = new Map();
const definedOrder = ['', '', '', ''];
definedOrder.forEach(k => {
if (itemDetails.hasOwnProperty(k)) {
attributes.set(k, itemDetails[k]);
}
});
const stateType = textify(itemDetails[''] ?? '');
if (stateType && itemDetails.hasOwnProperty('')) {
if (stateType.toLowerCase() !== '' || !attributes.has('')) {
attributes.set(stateType, itemDetails['']);
}
}
ActionResult"研究-新建"
- insert `//<>//<>`
- (0)
// 處理其他屬性,包括加值
Object.entries(itemDetails).forEach(([k, v]) => {
if (!attributes.has(k) && k !== '$meta' && k !== '' && k !== '') {
// 特別處理加值欄位
if (k === '' && v && typeof v === 'object') {
const bonusEntries = [];
Object.entries(v).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
attributes.set(k, bonusEntries.join(''));
} else {
attributes.set(k, v);
}
}
});
const postStateOrder = ['', '', '1', '2', '3', ''];
postStateOrder.forEach(k => {
if (itemDetails.hasOwnProperty(k)) {
attributes.set(k, itemDetails[k]);
}
});
attributes.forEach((v, k) => {
if (v !== null && v !== '' && v !== undefined) {
const line = $('<div>').addClass('item-prop');
// 如果是加值欄位,添加特殊類別
if (k === '') {
line.addClass('bonus-prop');
// 在加值前面添加分隔線
const separator = $('<div>').addClass('bonus-separator').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '10px 0 8px 0',
'width': '100%'
});
props.append(separator);
}
$('<span>').addClass('prop-key').text(String(k)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
let displayValue = textify(v, '');
if (k === '' && typeof v === 'number') {
displayValue += 'kg';
}
$('<span>').addClass('prop-val').text(displayValue).appendTo(line);
props.append(line);
// 如果是加值欄位,在後面也添加一個小分隔線
if (k === '') {
const bottomSeparator = $('<div>').css({
'height': '1px',
'background': 'rgba(148, 197, 255, 0.1)',
'margin': '8px 0 4px 0',
'width': '100%'
});
props.append(bottomSeparator);
}
}
});
####
itemCard.append(props);
}
inventoryContainer.append(itemCard);
});
}
cardBody.append(inventoryContainer);
card.append(cardHeader, cardBody);
cardHeader.on('click', () => {
card.toggleClass('active');
cardBody.slideToggle(200);
});
$body.append(card);
}
});
}
container.append($section);
}
- replace `//<>//<>/`
- replace `//<>//<>/`
- /
- replace
####
// ============== 新增:寵物渲染函數 ==============
function renderPets(container, petsSource) {
if (petsSource == null || Object.keys(petsSource).length === 0) return;
const { $section, $body } = d('', false);
const petEntries = toEntries(petsSource);
if (petEntries.length === 0) {
$body.append($('<p>').addClass('empty-text').text(''));
} else {
petEntries.forEach(([name, details]) => {
if (details && typeof details === 'object') {
const card = $('<div>').addClass('collapsible').css('margin-bottom', '10px');
const cardHeader = $('<div>').addClass('collapsible__header').text(name);
const cardBody = $('<div>').addClass('collapsible__body');
// 左側:狀態、關係、屬性
const leftCol = $('<div>').addClass('attr-col');
// 狀態(單獨一行)
const status = textify(details[''], '');
const statusRow = $('<div>').css({
'font-size': '16px',
'font-weight': 'bold',
'color': '#3498db',
'margin-bottom': '8px',
'text-align': 'left'
}).text(`: ${status}`);
leftCol.append(statusRow);
// 關係(單獨一行)
const relationship = textify(details[''] || details[''], '');
const relationshipRow = $('<div>').css({
'font-size': '16px',
'font-weight': 'bold',
'color': '#2ecc71',
'margin-bottom': '15px',
'text-align': 'left'
}).text(`: ${relationship}`);
leftCol.append(relationshipRow);
// 忠誠度(不顯示標題)
/* const loyalty = Math.min(Number(e(details[''] ?? 0)), 100);
leftCol.append(t(`: ${loyalty}/100 (${getLoyaltyStatus(loyalty)})`, loyalty, 100, 'loyalty-progress'));
// 性慾值(不顯示標題)
const desire = Math.min(Number(e(details[''] ?? 0)), 100);
leftCol.append(t(`: ${desire}/100`, desire, 100, 'pet-desire-progress')); */
// 屬性
const attributes = details[''] ?? {};
leftCol.append($('<div>').addClass('section__title').css('margin-top', '20px').text(''));
Object.entries(firstMeaningfulObject(attributes)).forEach(([attrName, attrDetails]) => {
if (attrDetails && typeof attrDetails === 'object') {
const level = Number(e(attrDetails[''] ?? 0));
const exp = Number(e(attrDetails[''] ?? 0));
const required = Number(e(attrDetails[''] ?? 1)) || 1;
leftCol.append($('<div>').text(`${attrName} Lv.${level}`), t('', exp, required));
}
});
// 右側:天賦特性(位置調整到前面)
const rightCol = $('<div>').addClass('skill-col');
// 先顯示天賦特性
const talents = details[''] ?? {};
const talentEntries = toEntries(talents);
if (talentEntries.length > 0) {
rightCol.append($('<div>').addClass('section__title').text(''));
talentEntries.forEach(([talentName, talentDetails]) => {
const item = $('<div>').addClass('skill-item');
// 天賦名稱
let displayName = talentName;
if (talentDetails && typeof talentDetails === 'object' && talentDetails.name) {
displayName = talentDetails.name;
}
$('<div>').addClass('skill-name').text(displayName).appendTo(item);
if (talentDetails && typeof talentDetails === 'object') {
// 先顯示描述
if (talentDetails['']) {
$('<div>').addClass('skill-desc').text(textify(talentDetails[''], '')).appendTo(item);
}
// 🔴 關鍵修改:分離處理「加值」和其他屬性
Object.entries(talentDetails).forEach(([key, value]) => {
if (key === '$meta' || key === 'name' || key === '') return;
if (key === '' && value && typeof value === 'object') {
// 加值特殊處理(跟主角/同伴一樣)
const bonusEntries = [];
Object.entries(value).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
// 添加分隔線(如果有其他內容)
const hasOtherContent = talentDetails[''] || Object.keys(talentDetails).some(k =>
k !== '$meta' && k !== 'name' && k !== '' && k !== ''
);
if (hasOtherContent) {
const separator = $('<div>').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '8px 0',
'width': '100%'
});
item.append(separator);
}
const bonusDiv = $('<div>').addClass('skill-desc').css({
'background': 'rgba(94, 161, 255, 0.08)',
'border-left': '3px solid var(--survival-accent)',
'padding': '6px 10px',
'border-radius': '4px',
'margin': '4px 0'
}).text(`${bonusEntries.join('')}`);
item.append(bonusDiv);
} else {
// 其他屬性正常顯示
$('<div>').addClass('skill-desc').text(`${key}${textify(value, '')}`).appendTo(item);
}
});
} else if (typeof talentDetails === 'string') {
$('<div>').addClass('skill-desc').text(talentDetails).appendTo(item);
}
rightCol.append(item);
});
}
// 然後顯示技能
const skills = details[''] ?? {};
const skillEntries = toEntries(skills);
rightCol.append($('<div>').addClass('section__title').css('margin-top', '20px').text(''));
if (skillEntries.length === 0) {
rightCol.append($('<p>').addClass('empty-text').text(''));
} else {
skillEntries.forEach(([skillName, skillDetails]) => {
if (skillDetails && typeof skillDetails === 'object') {
const level = Number(e(skillDetails[''] ?? 0));
const exp = Number(e(skillDetails[''] ?? 0));
const required = Number(e(skillDetails[''] ?? 1)) || 1;
rightCol.append($('<div>').addClass('skill-item').append(
$('<div>').addClass('skill-name').text(`${skillName} Lv.${level}`),
t('', exp, required)
));
}
});
}
// 將左右兩欄組合
const wrapper = $('<div>').addClass('attr-skill-wrapper');
wrapper.append(leftCol, rightCol);
cardBody.append(wrapper);
card.append(cardHeader, cardBody);
cardHeader.on('click', () => {
card.toggleClass('active');
cardBody.slideToggle(200);
});
$body.append(card);
}
});
}
container.append($section);
}
- remove `//<>//<>`
- insert `//<>/<>`
// 分类颜色
function getCategoryColor(category) {
const cat = (category || '').toLowerCase();
if (cat.includes('') || cat.includes('')) return '#e67e22';
if (cat.includes('') || cat.includes('')) return '#f39c12';
if (cat.includes('') || cat.includes('')) return '#27ae60';
if (cat.includes('') || cat.includes('')) return '#8e44ad';
if (cat.includes('') || cat.includes('')) return '#c0392b';
if (cat.includes('') || cat.includes('')) return '#2980b9';
return '#ffa502';
}
####
// 渲染扩展字段(材料、需求等)
function renderExtendedFields(container, data, skipKeys) {
if (!data || typeof data !== 'object') return;
const entries = Object.entries(data).filter(([k]) => !skipKeys.has(k) && !k.startsWith('$'));
if (entries.length === 0) return;
entries.forEach(([key, value]) => {
const fieldTitle = $('<div>').css({
'font-size': '12px',
'font-weight': 'bold',
'color': 'var(--survival-accent)',
'margin-top': '6px',
'margin-bottom': '4px'
}).text(key);
container.append(fieldTitle);
if (value && typeof value === 'object' && !Array.isArray(value)) {
const isMaterialStruct = Object.values(value).some(v => v && typeof v === 'object' && ('' in v || '' in v));
Object.entries(value).forEach(([subKey, subValue]) => {
if (isMaterialStruct && subValue && typeof subValue === 'object') {
const needed = Number(subValue[''] ?? 0);
const invested = Number(subValue[''] ?? 0);
const isCompleted = needed > 0 && invested >= needed;
const matLine = $('<div>').css({
'margin-left': '6px', 'line-height': '1.6', 'font-size': '11px',
'color': isCompleted ? '#888888' : '#cccccc',
'text-decoration': isCompleted ? 'line-through' : 'none'
});
$('<span>').css('color', isCompleted ? '#888888' : '#cccccc').text(`${subKey}`).appendTo(matLine);
$('<span>').css('color', isCompleted ? '#888888' : '#ffa502').text(`${invested}/${needed}`).appendTo(matLine);
if (isCompleted) $('<span>').css({ 'color': '#2ecc71', 'margin-left': '6px', 'font-size': '10px' }).text('').appendTo(matLine);
container.append(matLine);
} else {
const subLine = $('<div>').css({ 'margin-left': '6px', 'line-height': '1.6', 'font-size': '11px', 'color': '#cccccc' });
$('<span>').css('color', '#aaaaaa').text(`${subKey}`).appendTo(subLine);
$('<span>').css('color', '#ffa502').text(textify(subValue, '')).appendTo(subLine);
container.append(subLine);
}
});
} else if (Array.isArray(value)) {
const line = $('<div>').css({ 'margin-left': '6px', 'line-height': '1.6', 'font-size': '11px', 'color': '#cccccc' });
$('<span>').css('color', '#aaaaaa').text(`${key}`).appendTo(line);
$('<span>').css('color', '#ffa502').text(value.map(v => textify(v, '')).join('')).appendTo(line);
container.append(line);
} else {
const line = $('<div>').css({ 'margin-left': '6px', 'line-height': '1.6', 'font-size': '11px', 'color': '#cccccc' });
$('<span>').css('color', '#aaaaaa').text(`${key}`).appendTo(line);
$('<span>').css('color', '#ffa502').text(textify(value, '')).appendTo(line);
container.append(line);
}
});
}
-
-
// 核心:渲染项目、研究、知识库
function renderProgressAndKnowledge(container, statData) {
const projects = statData[''];
const research = statData[''];
const knowledge = statData[''];
let projectCount = 0, researchCount = 0, knowledgeCount = 0;
if (projects && typeof projects === 'object') projectCount = Object.keys(projects).filter(k => !k.startsWith('$')).length;
if (research && typeof research === 'object') {
for (const cat in research) {
if (cat.startsWith('$')) continue;
const ongoing = research[cat]?.[''];
if (ongoing && typeof ongoing === 'object') researchCount += Object.keys(ongoing).filter(k => !k.startsWith('$')).length;
}
}
if (knowledge && typeof knowledge === 'object') {
for (const cat in knowledge) {
if (cat.startsWith('$')) continue;
knowledgeCount += Object.keys(knowledge[cat] || {}).filter(k => !k.startsWith('$')).length;
}
}
if (projectCount === 0 && researchCount === 0 && knowledgeCount === 0) return;
const { $section: parentSection, $body: parentBody } = d('', false);
const skipProjectKeys = new Set(['', '', '', '', '', '']);
const skipResearchKeys = new Set(['', '', '']);
// 项目
if (projectCount > 0) {
const projStrip = $('<div>').addClass('task-strip side-task').css({ 'padding': '7px 16px', 'min-height': '31px', 'margin-top': '8px' });
$('<div>').addClass('task-content').css('color', '#f39c12').text('').appendTo(projStrip);
const projDetail = $('<div>').addClass('task-detail').hide();
const projContainer = $('<div>').addClass('progress-knowledge-card').css({ 'display': 'flex', 'flex-direction': 'column', 'gap': '6px', 'padding-top': '6px' });
for (const [name, proj] of Object.entries(projects || {})) {
if (name.startsWith('$') || !proj || typeof proj !== 'object') continue;
const card = $('<div>').css({ 'background': 'rgba(0,0,0,0.1)', 'border': '1px solid rgba(255,152,0,0.15)', 'border-radius': '6px', 'padding': '8px 10px' });
const titleRow = $('<div>').css({ 'display': 'flex', 'align-items': 'center', 'justify-content': 'center', 'gap': '6px', 'margin-bottom': '4px', 'flex-wrap': 'wrap' });
$('<div>').css({ 'font-size': '14px', 'font-weight': 'bold', 'color': '#ffa502', 'text-align': 'center' }).text(name).appendTo(titleRow);
const cat = textify(proj[''], '');
if (cat) {
const catColor = getCategoryColor(cat);
$('<div>').css({ 'display': 'inline-block', 'font-size': '8px', 'color': '#ffffff', 'background': catColor, 'padding': '0px 4px', 'border-radius': '6px', 'line-height': '1.4' }).text(cat).appendTo(titleRow);
}
card.append(titleRow);
const cur = Number(proj[''] ?? 0);
const max = Number(proj[''] ?? 100);
const progressWrapper = $('<div>').addClass('progress-wrapper');
$('<div>').css({ 'font-size': '12px', 'color': 'var(--survival-accent)' }).text('').append($('<span>').css('color', '#ffffff').text(`${cur}/${max}`)).appendTo(progressWrapper);
const bar = $('<div>').addClass('progress');
$('<div>').addClass('progress__bar').css('width', `${Math.max(0, Math.min(100, max === 0 ? 0 : (cur / max) * 100))}%`).appendTo(bar);
progressWrapper.append(bar);
card.append(progressWrapper);
const desc = textify(proj[''], '');
if (desc) $('<div>').css({ 'font-size': '11px', 'color': '#aaaaaa', 'line-height': '1.5', 'margin-top': '4px' }).text(desc).appendTo(card);
renderExtendedFields(card, proj, skipProjectKeys);
projContainer.append(card);
}
const projCollapseBtn = $('<div>').addClass('collapse-button').css({ 'padding': '4px 12px', 'line-height': '1.2' }).text('');
projCollapseBtn.on('click', (e) => { e.stopPropagation(); projDetail.slideUp(300); });
projDetail.append(projContainer, projCollapseBtn);
projStrip.on('click', () => projDetail.slideToggle());
parentBody.append(projStrip, projDetail);
}
### 14.
// 研究
if (researchCount > 0) {
const resStrip = $('<div>').addClass('task-strip main-task').css({ 'padding': '7px 16px', 'min-height': '31px', 'margin-top': '8px' });
$('<div>').addClass('task-content').css('color', '#3498db').text('').appendTo(resStrip);
const resDetail = $('<div>').addClass('task-detail').hide();
const resContainer = $('<div>').addClass('progress-knowledge-card').css({ 'display': 'flex', 'flex-direction': 'column', 'gap': '6px', 'padding-top': '6px' });
for (const [catName, catData] of Object.entries(research || {})) {
if (catName.startsWith('$') || !catData || typeof catData !== 'object') continue;
const ongoing = catData[''];
if (!ongoing || typeof ongoing !== 'object') continue;
for (const [resName, resItem] of Object.entries(ongoing)) {
if (resName.startsWith('$') || !resItem || typeof resItem !== 'object') continue;
const card = $('<div>').css({ 'background': 'rgba(0,0,0,0.1)', 'border': '1px solid rgba(52,152,219,0.15)', 'border-radius': '6px', 'padding': '8px 10px' });
const titleRow = $('<div>').css({ 'display': 'flex', 'align-items': 'center', 'justify-content': 'center', 'gap': '6px', 'margin-bottom': '4px', 'flex-wrap': 'wrap' });
$('<div>').css({ 'font-size': '14px', 'font-weight': 'bold', 'color': '#ffa502', 'text-align': 'center' }).text(resName).appendTo(titleRow);
const catColor = getCategoryColor(catName);
$('<div>').css({ 'display': 'inline-block', 'font-size': '8px', 'color': '#ffffff', 'background': catColor, 'padding': '0px 4px', 'border-radius': '6px', 'line-height': '1.4' }).text(catName).appendTo(titleRow);
card.append(titleRow);
const cur = Number(resItem[''] ?? 0);
const max = Number(resItem[''] ?? 100);
const progressWrapper = $('<div>').addClass('progress-wrapper');
$('<div>').css({ 'font-size': '12px', 'color': 'var(--survival-accent)' }).text('').append($('<span>').css('color', '#ffffff').text(`${cur}/${max}`)).appendTo(progressWrapper);
const bar = $('<div>').addClass('progress');
$('<div>').addClass('progress__bar').css('width', `${Math.max(0, Math.min(100, max === 0 ? 0 : (cur / max) * 100))}%`).appendTo(bar);
progressWrapper.append(bar);
card.append(progressWrapper);
const desc = textify(resItem[''], '');
if (desc) $('<div>').css({ 'font-size': '11px', 'color': '#aaaaaa', 'line-height': '1.5', 'margin-top': '4px' }).text(desc).appendTo(card);
renderExtendedFields(card, resItem, skipResearchKeys);
resContainer.append(card);
}
}
const resCollapseBtn = $('<div>').addClass('collapse-button').css({ 'padding': '4px 12px', 'line-height': '1.2' }).text('');
resCollapseBtn.on('click', (e) => { e.stopPropagation(); resDetail.slideUp(300); });
resDetail.append(resContainer, resCollapseBtn);
resStrip.on('click', () => resDetail.slideToggle());
parentBody.append(resStrip, resDetail);
}
####
// 知识库
if (knowledgeCount > 0) {
const knowStrip = $('<div>').addClass('task-strip bond-task').css({ 'padding': '7px 16px', 'min-height': '31px', 'margin-top': '8px' });
$('<div>').addClass('task-content').css('color', '#00cec9').text('').appendTo(knowStrip);
const knowDetail = $('<div>').addClass('task-detail').hide();
const knowContainer = $('<div>').addClass('progress-knowledge-card').css({ 'display': 'flex', 'flex-direction': 'column', 'gap': '4px', 'padding-top': '6px' });
for (const [catName, catItems] of Object.entries(knowledge || {})) {
if (catName.startsWith('$') || !catItems || typeof catItems !== 'object') continue;
const itemEntries = Object.entries(catItems).filter(([k]) => !k.startsWith('$'));
if (itemEntries.length === 0) continue;
$('<div>').css({ 'font-size': '12px', 'font-weight': 'bold', 'color': '#00cec9', 'border-bottom': '1px solid rgba(0,206,201,0.3)', 'padding-bottom': '4px', 'margin-top': '4px' }).text(catName).appendTo(knowContainer);
itemEntries.forEach(([itemName, itemData]) => {
const itemRow = $('<div>').css({ 'padding': '3px 0 3px 6px', 'font-size': '12px', 'line-height': '1.4' });
$('<span>').css({ 'color': '#ffa502', 'font-weight': 'bold' }).text(itemName).appendTo(itemRow);
const desc = textify(itemData?.[''] ?? '', '');
if (desc) $('<span>').css('color', '#cccccc').text(`${desc}`).appendTo(itemRow);
knowContainer.append(itemRow);
});
}
const knowCollapseBtn = $('<div>').addClass('collapse-button').css({ 'padding': '4px 12px', 'line-height': '1.2' }).text('');
knowCollapseBtn.on('click', (e) => { e.stopPropagation(); knowDetail.slideUp(300); });
knowDetail.append(knowContainer, knowCollapseBtn);
knowStrip.on('click', () => knowDetail.slideToggle());
parentBody.append(knowStrip, knowDetail);
}
container.append(parentSection);
}
- `//`
- `/` `//`
-
- `/`
- `//{}/{}/{}`
// ============== 修改版 renderGenericSection 函數(包含畜牧邏輯) ==============
function renderGenericSection(container, title, source, statData) {
if (source == null) return;
const entries = toEntries(source);
if (!entries || entries.length === 0) return;
// --- 特殊處理:基本資料(顯示為卡片式) ---
if (title === '') {
const { $section, $body } = d('', false);
const infoGrid = $('<div>').css({
'display': 'grid',
'grid-template-columns': 'repeat(auto-fit, minmax(200px, 1fr))',
'gap': '12px',
'margin-top': '10px'
});
entries.forEach(([key, value]) => {
const infoCard = $('<div>').css({
'background': 'rgba(30, 45, 70, 0.6)',
'border': '1px solid var(--survival-border)',
'border-radius': '8px',
'padding': '12px',
'text-align': 'center'
});
$('<div>').css({
'font-size': '14px',
'color': '#ffb86c',
'margin-bottom': '4px',
'font-weight': 'bold'
}).text(key).appendTo(infoCard);
$('<div>').css({
'font-size': '16px',
'color': 'var(--survival-text)'
}).text(textify(value, '--')).appendTo(infoCard);
infoGrid.append(infoCard);
});
$body.append(infoGrid);
container.append($section);
return;
}
// --- 特殊處理:如果標題是「捷徑或大型裝置」,使用獨立網格顯示 ---
if (title === '') {
const { $section, $body } = d(title, false);
const deviceGrid = $('<div>').addClass('inventory-grid');
entries.forEach(([name, data]) => {
if (data && typeof data === 'object') {
const cell = $('<div>').addClass('inventory-item');
$('<div>').addClass('item-name').text(name).appendTo(cell);
const props = $('<div>').addClass('item-props');
const objectProperties = {};
const simpleProperties = {};
Object.entries(data).forEach(([key, value]) => {
if (key === '$meta') return;
if (value !== null && value !== undefined && value !== '') {
if (typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length > 0) {
objectProperties[key] = value;
} else {
simpleProperties[key] = value;
}
}
});
Object.entries(simpleProperties).forEach(([key, value]) => {
const line = $('<div>').addClass('item-prop');
$('<span>').addClass('prop-key').text(String(key)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
$('<span>').addClass('prop-val').text(textify(value, '')).appendTo(line);
props.append(line);
});
Object.entries(objectProperties).forEach(([propertyName, propertyData]) => {
const objectLine = $('<div>').addClass('item-prop');
$('<span>').addClass('prop-key').text(propertyName).appendTo(objectLine);
$('<span>').addClass('prop-sep').text(': ').appendTo(objectLine);
const objectContent = $('<div>').addClass('object-content').css({
'display': 'flex',
'flex-direction': 'column',
'gap': '4px',
'margin-top': '4px'
});
Object.entries(propertyData).forEach(([itemName, itemData]) => {
if (itemName !== '$meta' && itemData !== null && itemData !== '') {
const itemLine = $('<div>').addClass('object-item').css({
'text-align': 'left',
'color': 'var(--survival-text)'
});
let quantity = '';
if (itemData && typeof itemData === 'object') {
if (itemData[''] !== undefined) {
quantity = `(:${itemData['']})`;
}
} else if (typeof itemData === 'number') {
quantity = `(:${itemData})`;
}
itemLine.text(`${itemName}${quantity}`);
objectContent.append(itemLine);
}
});
$('<span>').addClass('prop-val').append(objectContent).appendTo(objectLine);
props.append(objectLine);
});
cell.append(props);
deviceGrid.append(cell);
}
});
$body.append(deviceGrid);
container.append($section);
return;
}
// --- 以下是作物、畜牧、營地相關邏輯 ---
let overallCropStatusTag = '';
let overallLivestockStatusTag = '';
let overallCampTag = '';
let accelerationEffects = [];
let totalAcceleration = 0;
// 作物狀態標籤邏輯
if (title === '') {
const hasReadyCrop = entries.some(([, value]) => textify(value?.[''], '').includes(''));
overallCropStatusTag = `<span class="crop-status-indicator ${hasReadyCrop ? 'crop-status-ready' : 'crop-status-growing'}">${hasReadyCrop ? '' : ''}</span>`;
const currentSeason = textify(statData?.['']?.[''], '');
const seasonRules = {
'': { effect: 15, icon: '🌸' },
'': { effect: 20, icon: '' },
'': { effect: 0, icon: '🍁' },
'': { effect: -50, icon: '' }
};
if (seasonRules[currentSeason]) {
const seasonalEffect = seasonRules[currentSeason];
accelerationEffects.push({
name: `${currentSeason}`,
effect: seasonalEffect.effect,
icon: seasonalEffect.icon,
source: '',
order: 1
});
totalAcceleration += seasonalEffect.effect;
}
const equipment = statData?.[''] ?? {};
Object.entries(equipment).forEach(([itemName, itemData]) => {
if (itemData && typeof itemData === 'object') {
const cropBonus = Number(e(itemData[''] ?? 0));
if (cropBonus !== 0) {
accelerationEffects.push({
name: `${itemName}`,
effect: cropBonus,
icon: '🛡',
source: '',
order: 2
});
totalAcceleration += cropBonus;
}
}
});
const carriedItems = statData?.[''] ?? {};
Object.entries(carriedItems).forEach(([itemName, itemData]) => {
if (itemData && typeof itemData === 'object') {
const cropBonus = Number(e(itemData[''] ?? 0));
if (cropBonus !== 0) {
accelerationEffects.push({
name: `${itemName}`,
effect: cropBonus,
icon: '🧺',
source: '',
order: 3
});
totalAcceleration += cropBonus;
}
}
});
entries.forEach(([name, data]) => {
const growthStage = textify(data[''], '');
const cropBonus = Number(e(data[''] ?? 0));
if (growthStage.includes('') || cropBonus !== 0) {
const existing = accelerationEffects.find(eff => eff.name === name);
if (!existing) {
accelerationEffects.push({
name: `${name}`,
effect: cropBonus,
icon: '🌿',
source: '',
order: 4
});
totalAcceleration += cropBonus;
}
}
});
const companions = statData?.[''] ?? {};
Object.values(companions).forEach(companion => {
if (companion && typeof companion === 'object') {
const companionItems = companion[''] ?? {};
Object.entries(companionItems).forEach(([itemName, itemData]) => {
if (itemData && typeof itemData === 'object') {
const cropBonus = Number(e(itemData[''] ?? 0));
if (cropBonus !== 0) {
accelerationEffects.push({
name: `${itemName}`,
effect: cropBonus,
icon: '👥',
source: '',
order: 5
});
totalAcceleration += cropBonus;
}
}
});
}
});
}
####
// 畜牧狀態標籤邏輯
if (title === '') {
const currentDay = Number(e(statData?.['']?.[''] ?? 0));
let hasHarvestable = false;
entries.forEach(([, data]) => {
if (data && typeof data === 'object') {
const output = data[''];
if (output && output['']) {
const nextOutputDay = Number(e(output[''] ?? 0));
if (nextOutputDay <= currentDay) {
hasHarvestable = true;
}
}
}
});
if (hasHarvestable) {
overallLivestockStatusTag = `<span class="livestock-status-indicator livestock-status-harvest"></span>`;
} else {
overallLivestockStatusTag = `<span class="livestock-status-indicator livestock-status-none"></span>`;
}
}
| | |
|----------|------|
| | replace |
| | replace `//` |
| | insert |
| | remove |
| | remove + insert |
| | remove + insert |
| | replace |
// 🔴 營地存糧標籤邏輯(獨立放在這裡,與作物/畜牧同級)
if (title === '') {
const foodSupply = statData?.['']?.[''];
if (foodSupply !== undefined && foodSupply !== null) {
const days = Number(foodSupply);
let displayText = '';
let colorClass = '';
if (days <= 3) {
displayText = ` ${days.toFixed(1)} `; // 顯示小數點
colorClass = 'crop-status-danger'; // 🔴 紅色(警告)
} else {
displayText = ` ${days.toFixed(0)} `; // 顯示整數
colorClass = 'crop-status-ready'; // 🟢 綠色(正常)
}
overallCampTag = `<span class="crop-status-indicator ${colorClass}">${displayText}</span>`;
}
}
####
// --- 創建 section ---
const { $section, $header, $body } = d(title, false);
- `//{}/{}/{}`
- `////漿`
- `///漿`
// 🔴 添加所有標籤到標題(順序:營地存糧 → 作物 → 畜牧)
if (title === '' && overallCampTag) {
$header.append(overallCampTag);
}
if (overallCropStatusTag) $header.append(overallCropStatusTag);
if (overallLivestockStatusTag) $header.append(overallLivestockStatusTag);
// 作物加速效果顯示
if (title === '' && accelerationEffects.length > 0) {
const infoBox = $('<div>').addClass('crop-acceleration-info');
infoBox.append($('<div>').addClass('crop-acceleration-info__title').html('🏕 '));
accelerationEffects.sort((a, b) => {
if (a.order !== b.order) {
return a.order - b.order;
}
return b.effect - a.effect;
});
accelerationEffects.forEach(eff => {
const effectLine = $('<div>').addClass('crop-acceleration-info__item');
const effectText = eff.effect > 0 ? ` ${eff.effect} %` : ` ${Math.abs(eff.effect)} %`;
effectLine.html(`${eff.icon} ${eff.name}${effectText}`);
infoBox.append(effectLine);
});
const totalLine = $('<div>').addClass('crop-acceleration-info__total');
const totalActionText = totalAcceleration > 0 ? '' : '';
totalLine.html(` ${totalActionText}${Math.abs(totalAcceleration)} %`);
infoBox.append(totalLine);
$body.append(infoBox);
}
####
const firstValue = entries[0]?.[1];
let isItemCollection = false;
if (firstValue && typeof firstValue === 'object') {
const keys = Object.keys(firstValue);
const itemKeywords = ['', '', '', '', '', '', '', '', ''];
if (keys.some(k => itemKeywords.includes(k))) isItemCollection = true;
}
1. :
2. : XXXX
3. : XXXX
4. :
5. :
6. :
7. :
8. :
if (isItemCollection) {
const grid = $('<div>').addClass('inventory-grid');
entries.forEach(([name, data]) => {
if (title === '') {
const cycle = Number(e(data[''] ?? 0));
if (cycle < 0) return;
}
if (data && typeof data === 'object') {
const cell = $('<div>').addClass('inventory-item');
const itemNameDiv = $('<div>').addClass('item-name').text(data[''] || String(name));
if (title === '') {
const growthStage = textify(data[''], '');
if (growthStage) {
const isReady = growthStage.includes('');
const statusTag = $('<span>')
.addClass('crop-status-indicator')
.addClass(isReady ? 'crop-status-ready' : 'crop-status-growing')
.text(growthStage);
itemNameDiv.append(statusTag);
}
}
if (title === '') {
const currentDay = Number(e(statData?.['']?.[''] ?? 0));
let isHarvestable = false;
const output = data[''];
if (output && output['']) {
const nextOutputDay = Number(e(output[''] ?? 0));
if (nextOutputDay <= currentDay) {
isHarvestable = true;
}
}
if (isHarvestable) {
const statusTag = $('<span>')
.addClass('livestock-status-indicator')
.addClass('livestock-status-harvest')
.text('');
itemNameDiv.append(statusTag);
}
}
cell.append(itemNameDiv);
const props = $('<div>').addClass('item-props');
const attributes = new Map();
let definedOrder = [];
if (title === '') {
definedOrder = ['', '', '', '', '', ''];
} else if (title === '') {
definedOrder = ['', '', '', ''];
} else {
definedOrder = ['', '', '', ''];
}
definedOrder.forEach(k => {
if (data.hasOwnProperty(k)) attributes.set(k, data[k]);
});
const stateType = textify(data[''] ?? '');
if (stateType && data.hasOwnProperty('')) {
if (stateType.toLowerCase() !== '' || !attributes.has('')) {
attributes.set(stateType, data['']);
}
}
if (title === '') {
if (data.hasOwnProperty('')) {
attributes.set('', data['']);
}
} else {
const middleOrder = ['', '', '1', '2', '3'];
middleOrder.forEach(k => {
if (data.hasOwnProperty(k)) attributes.set(k, data[k]);
});
}
Object.entries(data).forEach(([k, v]) => {
if (!attributes.has(k) && k !== '$meta' && k !== '' && k !== '' && k !== '') {
attributes.set(k, v);
}
});
attributes.forEach((v, k) => {
if (v !== null && v !== '' && v !== undefined) {
if (k === 'harvestAction') return;
if (k === '') return;
const line = $('<div>').addClass('item-prop');
if (k === '') {
line.addClass('bonus-prop');
const separator = $('<div>').addClass('bonus-separator').css({
'height': '1px',
'background': 'linear-gradient(90deg, transparent, rgba(148, 197, 255, 0.4), transparent)',
'margin': '10px 0 8px 0',
'width': '100%'
});
props.append(separator);
}
$('<span>').addClass('prop-key').text(String(k)).appendTo(line);
$('<span>').addClass('prop-sep').text(': ').appendTo(line);
let displayValue = '';
if (typeof v === 'object') {
if (k === '') {
const objLines = [];
Object.entries(v).forEach(([subKey, subVal]) => {
if (subVal !== null && subVal !== '') {
objLines.push(`${subKey}: ${textify(subVal, '')}`);
}
});
displayValue = objLines.join(' | ');
} else if (k === '') {
const male = v[''] || 0;
const female = v[''] || 0;
const parts = [];
if (male > 0) parts.push(` x ${male}`);
if (female > 0) parts.push(` x ${female}`);
displayValue = parts.join('');
} else if (k === '') {
const bonusEntries = [];
Object.entries(v).forEach(([bonusKey, bonusValue]) => {
bonusEntries.push(`${bonusKey}+${bonusValue}`);
});
displayValue = bonusEntries.join('');
} else {
displayValue = '[...]';
}
} else {
displayValue = textify(v, '');
}
if (k === '' && typeof v === 'number') displayValue += 'kg';
if (k === '' && typeof v === 'number' && v > 0) displayValue += '';
if (k === '' && typeof v === 'number') displayValue += '%';
if (k === '' && typeof v === 'number') displayValue += '';
$('<span>').addClass('prop-val').text(displayValue).appendTo(line);
props.append(line);
if (k === '') {
const bottomSeparator = $('<div>').css({
'height': '1px',
'background': 'rgba(148, 197, 255, 0.1)',
'margin': '8px 0 4px 0',
'width': '100%'
});
props.append(bottomSeparator);
}
}
});
cell.append(props);
grid.append(cell);
}
});
$body.append(grid);
} else {
const campInfoContainer = $('<div>').addClass('camp-info-container');
if (title === '') {
const basicInfoEntry = entries.find(([key]) => key === '');
if (basicInfoEntry) {
const [keyName, value] = basicInfoEntry;
renderGenericSection(campInfoContainer, keyName, value, statData);
}
entries.forEach(([key, value]) => {
if (key === '') return;
if (value && typeof value === 'object') {
renderGenericSection(campInfoContainer, key, value, statData);
} else {
const infoLine = $('<div>').addClass('camp-info-item');
infoLine.append(
$('<span>').addClass('prop-key').text(String(key)),
$('<span>').addClass('prop-sep').text(': '),
$('<span>').addClass('prop-val').text(textify(value, '--'))
);
campInfoContainer.append(infoLine);
}
});
} else {
entries.forEach(([key, value]) => {
if (value && typeof value === 'object') {
renderGenericSection(campInfoContainer, key, value, statData);
} else {
const infoLine = $('<div>').addClass('camp-info-item');
infoLine.append(
$('<span>').addClass('prop-key').text(String(key)),
$('<span>').addClass('prop-sep').text(': '),
$('<span>').addClass('prop-val').text(textify(value, '--'))
);
campInfoContainer.append(infoLine);
}
});
}
$body.append(campInfoContainer);
}
container.append($section);
}
### 15.
async function p() {
try {
let messageId;
try {
messageId = typeof getCurrentMessageId === 'function' ? getCurrentMessageId() : getChatMessages('last')[0]?.message_id;
} catch(e) {
messageId = getChatMessages('last')[0]?.message_id;
}
// 關鍵修改:無法獲取消息ID時靜默返回,不報錯
if (!messageId) {
console.log('...');
return;
}
####
const message = getChatMessages(messageId)[0];
if (!message) {
return;
}
| | | |
|------|----------|------|
| | 0-10 | 4 |
| | 11-30 | |
| | 31-90 | |
| | 91-210 | |
| | 211-360 | |
| | 361-365 | |
const data = message?.data ?? {}, statData = data.stat_data ?? {}, displayData = data.display_data ?? {};
if (Object.keys(statData).length === 0 && Object.keys(displayData).length === 0) return;
const $root = $('#survival-ui').empty();
const get = (key) => statData?.[key] ?? displayData?.[key];
r($root, statData);
createStatusEffects($root, statData);
const { $section: statusSection, $body: statusBody } = d('', false);
renderUnifiedStatus(statusBody, statData);
$root.append(statusSection);
const { $section: skillSection, $body: skillBody } = d(' & ', false);
renderAttributesAndSkills(skillBody, get(''), get(''), get(''));
$root.append(skillSection);
renderCompanions($root, get(''));
renderPets($root, get(''));
// 這裡新增畜牧的渲染 - 在作物和捷徑之間
['', '', '', ''].forEach(title => renderGenericSection($root, title, get(title), statData));
renderTaskSystem($root, statData);
renderProgressAndKnowledge($root, statData);
const survivalPoints = Number(e(statData['']?.[''])) || 0; // 改成求生點數
const buttonBar = $('<div>').addClass('button-container');
buttonBar.append(
$('<button>').addClass('action-btn draw-btn survival').text(` (${survivalPoints})`).on('click', () => showDrawConfirmModal('survival', survivalPoints)), // 只傳一個參數
$('<button>').addClass('action-btn').text('').on('click', () => openImageViewerModal(statData, displayData)),
$('<button>').addClass('action-btn').text('').on('click', () => i(get(''), get(''), get(''), Number(e(statData['']?.[''] ?? 0)), Number(e(statData['']?.[''] ?? 50)), false))
);
$root.append(buttonBar);
} catch (error) {
console.error('UI:', error);
}
}
####
- : 365
- :
-
-
-
-
####
- : +1/+3+1/
- : 8-2/-10
####
- :
- : 20
### 16.
🔴 ActionResult ()
####
- : insert(`//`, {, , , , , , harvestAction, ()})
- :
🔴
- ``
-
- ``
- 20 20%
- :
- :
1. insert
2. remove `//{}` ( harvestAction REMOVE RESET)
🔴 harvestAction = RESET remove
####
- : insert(`//`, {, , , , })
- :
- : insert
- : replace
- : 2
- : 1d100=1-5 +1
### 17.
- : insert(`//`, {, , , , })
### 18. JSONPatch
1. "數據源當前狀態""推導出的變化"
2.
3.
JSONPatch
#### 🔴
1.
2.
3. /
4. ActionResultActionResult使ActionResult
5. //8
6. ActionResult"無"
7. insert
8.
9. `//` `//{}/...`
10. JSON Patch `//` replace
11. / ActionResult JSON Patch
12.
13. `//`
#### 🔴
`<JSONPatch>` AI `path`
1. ``
2. `path` 100%
3. **** JSON Patch AI Patch
##
<UpdateVariable>
<Analysis>
<status_current_variable>
### ActionResult
- [][]XX
- [/]
- : []
- =[] / =[] / =[] / =[] / =[] / =[]
- [[] + / ]
- ()[[/]:[]×[][REMOVE] / ]
- : [[] +20% +40% / ]
- [ + / ]
- [/]
-
- [/]
- [+ / ]
- [:[] / :[] X%Y% /:[]×[] / :[] :/ / :[] / ]
- :
- : []
- : [/]
- : [/]
- : []
- : [////]
- : [/調//]
- : [0-100]
- : [-// / -... / -...]
- : []
- :
- : [:[] / :[/]]
- :
- :[]
- :[]
- :[]
- :[]
- /[ / ]
###
-
-
-
- .: ActionResult[//]
-
- ActionResult ______
- `//` ______
- `//`
###
[/] 00:00
- [/]
-
- [{}"XXX" / ]
- [: ±X]
- [: XY:/]
- [: () / ()]
- [: -5 XY / ]
### ()
ActionResult ()
-
1. insert `//{}//{}`
2. remove `//{}`()
1. insert `//{}//{}`
2. replace `//{}/` = N
###
- []
- []
- []
### <user>
- /
### <user>
- = //// = `//{}`
- = // = `//{}`
- = //// = `//{}`
<user>
- AI (/)////////
- .: [X]°C []~[]°C [X]°C [±Y]°C
- /[ +XX +X +X...]
- [:0-X ]
- /[ +X]
- []
[]
-
- [: +X+X / : / +X / -X / ]
[]
- [ -X / -X / : +X / : / ]
###
[]:
: []
: [X] / []
: [ / ]
: [ X+1 / ]
: []
###
()
- :[]
- :[]
- :[]
- :[]
### BB
- <sex_rules> 891011
- [+1 / ]
- [ ]
- [ / / / ]
- [//][±]
- [ + //// /]
- [ ]
###
- []
- [/]
- [X%]
- [ / / / / / ]
- [×0.5/ ×1.0/ ]
- [ / / / ]
- [-X]
- [+X]
- [/]
- [ / +10 / ]
-
- =
- replace `//{}//` "流產"
- replace `//{}//` 0
- replace `//{}//` 0
- replace `//{}//` + 1
- replace `//{}//`
- replace `//{}//` 0
- delta `//{}//` -[]
- delta `//{}//` -15
- delta `//{}//` +[]
- remove = {}
- replace `//{}//` true
- =
- = +10replace `//{}//` + 10
- = replace `//{}//` 0
###
- [/]00:00
- [/]
-
- <>
- (1kg)()使
-
1. `//`
- {{get_message_variable::stat_data...}}
- {{get_message_variable::stat_data...}}
- {{get_message_variable::stat_data...}}
- {{get_message_variable::stat_data...}}
- -{{get_message_variable::stat_data...-}}
- -{{get_message_variable::stat_data...-}}
- -{{get_message_variable::stat_data...-}}
- -{{get_message_variable::stat_data...-}}
2.
- -[///]
- -[//]
- -[////]
- -[/]
3.
- [ ]
- [ ]
- [ ]
- -[ ]
- -[ ]
- -[ ]
- -[ ]
- [ ]
- [ ]
4. 🔴
-
-
- [ / XXX]
5. [ / XXX]
- 🔴
| | | | | |
|------|--------|----------|----------|------|
| | XXX | XXX | [] | / |
| | XXX | XXX | [] | / |
| ... | ... | ... | ... | ... |
- 3
- [ / ]
###
- [ / :X / :100 / : / []×[] / :XX]
- [ / X%Y% / []×[] / :/]
- [ / :X / :/]
- [ / / :XX]
- "無"
###
- [ / / :X]
- [ / / XY]
- [ / / ]
- "無"
###
-
- = ///// = `//{}`
- = `//{}`
- **user**
-
- `.*.`
- : []
- : +[X]
- : `//[]/[/]/[]`
- : [/]
- : [ / ]
- : [delta/insert]
###
- 🔴
- ______
- ______
###
****
- [ / : XY ]
- [ / : :N/R/SR/UR::100:X:"..."]
- [ / / ]
- [ + ]
- [ + /]
- [ / / ]
###
- []
- [/]
- [/]
- []
- [////]
- [/調//]
- [0-100]
- [-// / -... / -...]
- []
- [ //]
###
####
:
:
:
- [: (/)]
:
- [: (/)]
:
:
- [: (/)]
:
- [: (/)]
:
:
- [ / ]
:
:
- [: / ]
:
- [: / ]
:
:
- [: / ]
:
- [: / ]
:
[]:
:
- [: (/)]
:
- [: (/)]
####
- : [ / {} / {}]
- : []
- : []
- : []
- : []
- : (
[]: [ / {} / {}]
[][]
####
1. /
2. +
3. = ÷
4.
- /
- /
-
- ×101/2 = 10÷2 = 5
- 1 = 9÷2 = 4.5
####
JSON Patch `//`
###
####
/
- /: [] / +[X] / : `/[]/[/]/[]` / [/] / [delta/insert]
- []×[] / / / / / :[]
- []
🔴
- [/]
- /[/]
- [/]
- [ / ]
####
:
: [ / ]
: [ / ]
:
:
: [ / ]
: [ / ]
:
:
: [ / ]
:
: [ / ]
: [ / ]
:
:
: [ / ]
: [ / ]
:
:
[]:
: [ / ]
: [ / ]
: `//[]/[/]/[]`
###
- .[/]
- [/]
- [/]
- [/]
###
🔴
- ______
- ______
-
- `//{}/{/}/{N}`
- `//{}/{/}/{N}`
- [ / ]
- []
-
- `//`
- `//`
- [/]
- `/` ______
- `/`
- `//{}//`
- [ / ]
###
- 1.
- 2.
- 3.
- 4. /
- 5.
- 6.
###
-
-
-
- ActionResult"無"= = = = = = =
-
-
</Analysis>
<JSONPatch>
$(() => {
try {
p();
const rerender = () => p();
if (typeof eventOn === 'function') eventOn('mag_variable_update_ended', rerender);
$(window).on('unload', () => typeof eventRemoveListener === 'function' && eventRemoveListener('mag_variable_update_ended', rerender));
} catch (error) {
console.error('UI:', error);
}
});
</script></body></html>
```
[
]
</JSONPatch>
</UpdateVariable>