koishi-plugin-dew-bot 1.0.264 → 1.0.265
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/lib/index.js +84 -10
- package/lib/plugin/companionCardAssets.d.ts +1 -0
- package/lib/plugin/companionCardStyles.d.ts +1 -1
- package/lib/plugin/companionCardTemplate.d.ts +1 -1
- package/lib/shared/bot/PtlStatistics.d.ts +1 -1
- package/lib/shared/face/index.d.ts +12 -2
- package/package.json +1 -1
- package/src/plugin/companionCardAssets.ts +2 -0
- package/src/plugin/companionCardStyles.ts +6 -0
- package/src/plugin/companionCardTemplate.ts +17 -8
- package/src/plugin/skillCard.ts +2 -1
- package/src/shared/bot/PtlStatistics.ts +1 -1
- package/src/shared/bot/serviceProto.ts +58 -1
- package/src/shared/face/index.ts +5 -1
package/README.md
CHANGED
package/lib/index.js
CHANGED
|
@@ -67,7 +67,7 @@ var serviceProto;
|
|
|
67
67
|
var init_serviceProto = __esm({
|
|
68
68
|
"src/shared/bot/serviceProto.ts"() {
|
|
69
69
|
serviceProto = {
|
|
70
|
-
"version":
|
|
70
|
+
"version": 42,
|
|
71
71
|
"services": [
|
|
72
72
|
{
|
|
73
73
|
"id": 0,
|
|
@@ -1828,6 +1828,55 @@ var init_serviceProto = __esm({
|
|
|
1828
1828
|
]
|
|
1829
1829
|
}
|
|
1830
1830
|
}
|
|
1831
|
+
},
|
|
1832
|
+
{
|
|
1833
|
+
"id": 14,
|
|
1834
|
+
"name": "equipment",
|
|
1835
|
+
"type": {
|
|
1836
|
+
"type": "Array",
|
|
1837
|
+
"elementType": {
|
|
1838
|
+
"type": "Interface",
|
|
1839
|
+
"properties": [
|
|
1840
|
+
{
|
|
1841
|
+
"id": 0,
|
|
1842
|
+
"name": "id",
|
|
1843
|
+
"type": {
|
|
1844
|
+
"type": "String"
|
|
1845
|
+
}
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
"id": 1,
|
|
1849
|
+
"name": "name",
|
|
1850
|
+
"type": {
|
|
1851
|
+
"type": "String"
|
|
1852
|
+
}
|
|
1853
|
+
},
|
|
1854
|
+
{
|
|
1855
|
+
"id": 2,
|
|
1856
|
+
"name": "quality",
|
|
1857
|
+
"type": {
|
|
1858
|
+
"type": "String"
|
|
1859
|
+
}
|
|
1860
|
+
},
|
|
1861
|
+
{
|
|
1862
|
+
"id": 3,
|
|
1863
|
+
"name": "slot",
|
|
1864
|
+
"type": {
|
|
1865
|
+
"type": "String"
|
|
1866
|
+
}
|
|
1867
|
+
},
|
|
1868
|
+
{
|
|
1869
|
+
"id": 4,
|
|
1870
|
+
"name": "enhancement",
|
|
1871
|
+
"type": {
|
|
1872
|
+
"type": "Number"
|
|
1873
|
+
},
|
|
1874
|
+
"optional": true
|
|
1875
|
+
}
|
|
1876
|
+
]
|
|
1877
|
+
}
|
|
1878
|
+
},
|
|
1879
|
+
"optional": true
|
|
1831
1880
|
}
|
|
1832
1881
|
]
|
|
1833
1882
|
},
|
|
@@ -1841,6 +1890,14 @@ var init_serviceProto = __esm({
|
|
|
1841
1890
|
{
|
|
1842
1891
|
"id": 1,
|
|
1843
1892
|
"value": "follower"
|
|
1893
|
+
},
|
|
1894
|
+
{
|
|
1895
|
+
"id": 2,
|
|
1896
|
+
"value": "monster"
|
|
1897
|
+
},
|
|
1898
|
+
{
|
|
1899
|
+
"id": 3,
|
|
1900
|
+
"value": "boss"
|
|
1844
1901
|
}
|
|
1845
1902
|
]
|
|
1846
1903
|
},
|
|
@@ -2986,6 +3043,12 @@ var companionCardStyles = `
|
|
|
2986
3043
|
.companion-attributes{margin-top:3px;flex:1;display:flex;flex-direction:column;justify-content:center;min-width:0}.companion-attributes .ornament-heading{margin-bottom:4px;font-size:22px;gap:6px;letter-spacing:2px}.companion-radar{width:100%;height:300px;display:block;overflow:visible}.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.2}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.5;stroke-linejoin:round}.radar-dot{fill:var(--flower);stroke:var(--radar);stroke-width:2}.radar-label{font:18px "Microsoft YaHei",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,"Microsoft YaHei",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 "Microsoft YaHei",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 "Microsoft YaHei",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}
|
|
2987
3044
|
.companion-skills{position:relative;z-index:1;padding:12px 18px 19px;margin-top:15px}.companion-skills .ornament-heading{margin-bottom:13px}.skill-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 13px}.companion-skill{position:relative;min-width:0;display:grid;grid-template-columns:47px minmax(0,1fr) auto;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--edge);border-radius:7px;box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--edge) 12%,transparent);background:color-mix(in srgb,var(--panel) 55%,transparent);min-height:65px}.skill-icon{width:47px;height:47px;border:1px solid var(--edge);border-radius:7px;display:grid;place-items:center;background:radial-gradient(ellipse at 40% 23%,color-mix(in srgb,var(--accent) 55%,var(--paper)),color-mix(in srgb,var(--paper) 72%,#282015));color:var(--flower);box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--light-edge) 20%,transparent)}.skill-icon svg{width:31px;height:31px;stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}.skill-name{font-size:20px;font-weight:700;overflow-wrap:anywhere;line-height:1.35}.skill-level{font:18px/1.2 Georgia,"Microsoft YaHei",serif;border:1px solid color-mix(in srgb,var(--edge) 55%,transparent);border-radius:13px;padding:5px 9px;white-space:nowrap;color:var(--ink);background:color-mix(in srgb,var(--accent) 9%,transparent)}.empty-list{margin:10px 0;color:var(--subtle);font:17px/1.6 "Microsoft YaHei",sans-serif;text-align:center}.follower-theme .companion-panel{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 50%,transparent),0 2px 6px #00000040}.follower-theme .skill-icon{background:radial-gradient(ellipse at 40% 23%,#858585,#292929)}.follower-theme .resource-track{box-shadow:inset 0 1px 3px #00000030}.follower-theme .companion-power{color:var(--ink)}.follower-theme .resource-percent{color:#fffef7;text-shadow:0 1px 2px #242725}
|
|
2988
3045
|
.skill-icon,.bloodline-crest{position:relative;overflow:hidden}.bloodline-crest.has-entry-artwork{border-radius:7px}.skill-entry-artwork,.bloodline-entry-artwork{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;border-radius:inherit;background:var(--paper);z-index:1}.follower-theme .skill-entry-artwork,.follower-theme .bloodline-entry-artwork{filter:grayscale(1)}
|
|
3046
|
+
.monster-theme{--ink:#e0eeea;--subtle:#a2b9b6;--accent:#9bd8c9;--edge:#668f90;--light-edge:#c3e5d7;--panel:#203f48;--panel-deep:#142d38;--paper:#183440;--flower:#d3efe6;--track:#213c46;--track-edge:#769b92;--health:#518f7f;--health-light:#96d6b5;--radar:#a2d8c9;--radar-fill:#7bb5ab55;--radar-grid:#507d80;background:radial-gradient(ellipse at 10% 9%,#81b8a840,transparent 43%),radial-gradient(ellipse at 94% 83%,#49808045,transparent 35%),repeating-linear-gradient(125deg,#d6eee608 0 1px,transparent 1px 5px),linear-gradient(155deg,#3c6269,#142a35 37%,#30515a)}
|
|
3047
|
+
.boss-theme{--ink:#f7e2c3;--subtle:#ceafac;--accent:#edc385;--edge:#b77c62;--light-edge:#f5dba4;--panel:#492937;--panel-deep:#281b2a;--paper:#342132;--flower:#ffe6b2;--track:#4b2837;--track-edge:#b88170;--health:#a24d59;--health-light:#eb9395;--radar:#edc385;--radar-fill:#daaa5b55;--radar-grid:#925c64;padding-top:55px;background:radial-gradient(ellipse at 48% 0%,#ecc07855,transparent 40%),radial-gradient(ellipse at 96% 83%,#c54a6245,transparent 35%),repeating-linear-gradient(125deg,#f2dfbd08 0 1px,transparent 1px 5px),linear-gradient(155deg,#773b46,#211b2c 37%,#5d2c42)}
|
|
3048
|
+
.boss-card-decoration{position:absolute;top:3px;left:50%;transform:translateX(-50%);width:160px;height:52px;color:var(--accent)}.boss-card-decoration svg{display:block;width:100%;height:100%}.boss-theme .companion-portrait,.boss-theme .companion-stats{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 60%,transparent),0 0 13px #daa04e40}.boss-theme .state-badge{border-radius:5px;letter-spacing:3px;background:linear-gradient(135deg,#b6805130,#8c44502b);padding:7px 15px}.monster-theme .state-badge{letter-spacing:2px}
|
|
3049
|
+
.enemy-equipment{padding:13px 18px 18px;margin-top:15px}.enemy-equipment-list{display:grid;gap:8px}.enemy-equipment-row{display:grid;grid-template-columns:28px minmax(0,1fr) auto auto;align-items:center;gap:10px;padding:8px 11px;border:1px solid var(--edge);border-radius:7px;background:color-mix(in srgb,var(--panel) 55%,transparent);min-width:0}.equipment-symbol{color:var(--accent);font-size:26px}.enemy-equipment-name{font-size:20px;line-height:1.4;overflow-wrap:anywhere}.enemy-equipment-name small{color:var(--accent);font:17px Georgia,serif;white-space:nowrap}.equipment-slot{font:15px/1.4 "Microsoft YaHei",sans-serif;color:var(--subtle);max-width:120px;overflow-wrap:anywhere}
|
|
3050
|
+
.enemy-main{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.enemy-sheet .companion-stats{justify-content:center;padding:24px 24px 26px}.enemy-sheet .companion-name{font-size:43px;letter-spacing:2px}.enemy-sheet .companion-power-row{margin:24px 0}.enemy-sheet .companion-resource{margin-bottom:0}.enemy-attributes{padding:16px 12px 12px;display:flex;align-items:center}.enemy-attributes .companion-attributes{margin:0}.enemy-sheet>.bloodline-panel{margin-top:15px;padding:13px 18px 18px}.enemy-sheet .bloodline-list{grid-template-columns:repeat(2,minmax(0,1fr))}.enemy-sheet .bloodline-name{font-size:20px}
|
|
3051
|
+
|
|
2989
3052
|
`;
|
|
2990
3053
|
|
|
2991
3054
|
// src/plugin/companionCardAssets.ts
|
|
@@ -3018,6 +3081,7 @@ var followerPortraitPlaceholder = image(`<svg xmlns="http://www.w3.org/2000/svg"
|
|
|
3018
3081
|
<g fill="#1d1d1d" stroke="#a7a7a7" stroke-width="2"><path d="M158 485c7-79 20-135 42-166 15-44 29-83 70-88 46 7 58 45 73 89 19 29 37 87 42 166Z"/><path d="M218 297c-4-50 14-87 52-88 39 1 58 38 52 89l-19-9-13-30-20-12-22 12-11 30Z"/><path d="m216 316 54 66 54-66M197 358l-26 117m172-117 27 117" fill="none"/><path d="m247 287 23 20 24-20-11 48h-26Z" fill="#808080" stroke="none"/></g>
|
|
3019
3082
|
<text x="270" y="551" text-anchor="middle" font-family="Microsoft YaHei,sans-serif" font-size="26" letter-spacing="4" fill="#e1e0d6">暂无随从形象</text>
|
|
3020
3083
|
</svg>`);
|
|
3084
|
+
var bossCardDecoration = '<svg viewBox="0 0 160 64" aria-hidden="true"><path d="M31 49 23 17l32 20L80 5l25 32 32-20-8 32ZM31 55h98" fill="currentColor" opacity=".7"/><path d="M9 51 26 39M134 39l17 12M5 58l19-10m112 0 19 10" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="80" cy="5" r="4" fill="currentColor"/><circle cx="23" cy="17" r="3" fill="currentColor"/><circle cx="137" cy="17" r="3" fill="currentColor"/></svg>';
|
|
3021
3085
|
|
|
3022
3086
|
// src/plugin/companionCardTemplate.ts
|
|
3023
3087
|
var finite2 = /* @__PURE__ */ __name((value) => Number.isFinite(value) ? value : 0, "finite");
|
|
@@ -3086,21 +3150,30 @@ function skills(card, icons) {
|
|
|
3086
3150
|
return `<section class="companion-panel companion-skills" aria-label="技能">${corners2()}${heading("技能")}${card.skills.length ? `<div class="skill-grid">${card.skills.map((skill, index) => `<div class="companion-skill" data-skill-id="${cardEscape(skill.id)}"><span class="skill-icon" aria-hidden="true"><svg viewBox="0 0 36 36">${skill.type === "passive" ? passive : active}</svg>${icons?.skills?.[index] ? `<img class="skill-entry-artwork" data-entry-index="${index}" src="${cardEscape(icons.skills[index])}" alt="">` : ""}</span><span class="skill-name">${cardEscape(skill.name)}</span><span class="skill-level">Lv.${number3(skill.rank)}</span></div>`).join("")}</div>` : '<p class="empty-list">暂无技能</p>'}</section>`;
|
|
3087
3151
|
}
|
|
3088
3152
|
__name(skills, "skills");
|
|
3153
|
+
function equipment(card) {
|
|
3154
|
+
if (!card.equipment) return "";
|
|
3155
|
+
return `<section class="companion-panel enemy-equipment" aria-label="装备">${heading("装备")}${card.equipment.length ? '<div class="enemy-equipment-list">' + card.equipment.map((item) => `<div class="enemy-equipment-row"><span class="equipment-symbol" aria-hidden="true">✧</span><span class="enemy-equipment-name">${cardEscape(item.name)}${item.enhancement ? " <small>+" + number3(item.enhancement) + "</small>" : ""}</span><span class="equipment-slot">${cardEscape(item.slot)}</span><span class="bloodline-quality">${cardEscape(item.quality)}</span></div>`).join("") + "</div>" : '<p class="empty-list">暂无装备</p>'}</section>`;
|
|
3156
|
+
}
|
|
3157
|
+
__name(equipment, "equipment");
|
|
3089
3158
|
function companionCardHtml(card, artwork, icons) {
|
|
3090
3159
|
const pet = card.kind === "pet";
|
|
3160
|
+
const enemy = card.kind === "monster" || card.kind === "boss";
|
|
3161
|
+
const boss = card.kind === "boss";
|
|
3162
|
+
const kind = enemy ? boss ? "boss" : "monster" : pet ? "pet" : "follower";
|
|
3163
|
+
const typeName = enemy ? boss ? "首领" : "普通怪物" : pet ? "宠物" : "随从";
|
|
3091
3164
|
const fallback = pet ? petPortraitPlaceholder : followerPortraitPlaceholder;
|
|
3092
3165
|
const healthPercent = ratio2(card.hp, card.maxHp) * 100;
|
|
3093
3166
|
const experience = Math.max(0, Math.min(100, finite2(card.experiencePercent ?? 0)));
|
|
3094
3167
|
const state = pet ? card.state === "fallen" ? "fallen" : card.state === "resting" ? "resting" : "active" : "active";
|
|
3095
|
-
const stateName = pet ? { active: "出战", resting: "休息", fallen: "倒下" }[state] : "自动参战";
|
|
3096
|
-
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>${companionCardStyles}</style></head><body><main id="capture" class="companion-sheet ${
|
|
3097
|
-
|
|
3098
|
-
<section class="companion-panel companion-stats" aria-label="${
|
|
3168
|
+
const stateName = enemy ? typeName : pet ? { active: "出战", resting: "休息", fallen: "倒下" }[state] : "自动参战";
|
|
3169
|
+
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>${companionCardStyles}</style></head><body><main id="capture" class="companion-sheet ${kind}-theme${enemy ? " enemy-sheet" : ""}" data-kind="${kind}">${boss ? `<div class="boss-card-decoration">${bossCardDecoration}</div>` : ""}<div class="companion-main${enemy ? " enemy-main" : ""}">
|
|
3170
|
+
${enemy ? "" : `<div class="portrait-column"><div class="companion-panel companion-portrait">${corners2()}<div class="portrait-window"><img id="companion-image" class="companion-artwork" src="${cardEscape(artwork || fallback)}" data-fallback="${cardEscape(fallback)}" alt="${cardEscape(card.name)}的形象图"></div></div>${card.description?.trim() ? `<p class="companion-description">${cardEscape(card.description.trim())}</p>` : ""}${bloodlines(card, icons)}</div>`}
|
|
3171
|
+
<section class="companion-panel companion-stats" aria-label="${typeName}属性">${corners2(["tr", "br"])}<div class="companion-identity"><h1 id="companion-name" class="companion-name">${cardEscape(card.name)}</h1><p class="companion-level">Lv. ${number3(card.level)}</p><div class="state-badge state-${state}">${pet ? paw : '<span aria-hidden="true">✦</span>'}<span>${stateName}</span>${pet ? paw : '<span aria-hidden="true">✦</span>'}</div>${kind === "follower" ? '<p class="permanent-note">战死后永久离队</p>' : ""}</div>
|
|
3099
3172
|
<div class="companion-power-row"><span class="power-icon" aria-hidden="true">${sword}</span><span class="companion-power-label">战力</span><strong id="companion-power" class="companion-power">${number3(card.power)}</strong></div>
|
|
3100
3173
|
<div class="companion-resource hp-resource"><div class="resource-heading"><span class="resource-label"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="M16 28C6 21 2 17 2 10a7 7 0 0 1 14-2 7 7 0 0 1 14 2c0 7-4 11-14 18Z"/></svg>生命值</span><span id="companion-hp" class="resource-number">${number3(card.hp)} / ${number3(card.maxHp)}</span></div><div class="resource-track" role="progressbar" aria-label="生命值" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${healthPercent}"><span class="resource-fill" style="width:${healthPercent}%"></span><span class="resource-percent">${number3(healthPercent)}%</span></div></div>
|
|
3101
3174
|
${pet ? `<div class="companion-resource exp-resource"><div class="resource-heading"><span class="resource-label"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="m16 2 4.5 9.1 10 1.4-7.3 7.1 1.7 10-8.9-4.7-8.9 4.7 1.7-10-7.3-7.1 10-1.4Z"/></svg>经验进度</span><span class="resource-number">${number3(experience)}%</span></div><div class="resource-track" role="progressbar" aria-label="经验进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${experience}"><span class="resource-fill" style="width:${experience}%"></span><span class="resource-percent">${number3(experience)}%</span></div></div>` : ""}
|
|
3102
|
-
<section class="companion-attributes" aria-label="一级属性">${heading("一级属性")}${radar2(card)}</section></section>
|
|
3103
|
-
</div>${skills(card, icons)}</main></body></html>`;
|
|
3175
|
+
${enemy ? '</section><section class="companion-panel enemy-attributes">' : ""}<section class="companion-attributes" aria-label="一级属性">${heading("一级属性")}${radar2(card)}</section></section>
|
|
3176
|
+
</div>${enemy ? bloodlines(card, icons) : ""}${skills(card, icons)}${equipment(card)}</main></body></html>`;
|
|
3104
3177
|
}
|
|
3105
3178
|
__name(companionCardHtml, "companionCardHtml");
|
|
3106
3179
|
|
|
@@ -3692,8 +3765,8 @@ function bloodlineCardHtml(card, artwork) {
|
|
|
3692
3765
|
const nextExperience = finite4(card.nextExperience ?? 0);
|
|
3693
3766
|
const experience = Math.max(0, finite4(card.experience ?? 0));
|
|
3694
3767
|
const experienceHtml = card.experience === void 0 ? "" : nextExperience > 0 ? `<div class="experience-block"><div class="experience-label"><span>血统经验</span><b>${number5(experience)}<small> / ${number5(nextExperience)}</small></b></div><div class="experience-track"><i style="width:${Math.max(0, Math.min(100, experience / nextExperience * 100))}%"></i></div>${card.nextQuality ? `<div class="experience-next">下一级品质 <b>${cardEscape(card.nextQuality.replace(/\s*级$/, ""))} 级</b></div>` : ""}</div>` : `<div class="experience-block"><div class="experience-label"><span>血统经验</span><b>${number5(experience)}</b></div><div class="experience-next"><b>已达最高品质</b></div></div>`;
|
|
3695
|
-
const
|
|
3696
|
-
const unlocks =
|
|
3768
|
+
const equipment2 = [...card.equipmentTypes].sort((a, b) => Number(/^[a-z]/i.test(a.type)) - Number(/^[a-z]/i.test(b.type)));
|
|
3769
|
+
const unlocks = equipment2.length ? `<div class="equipment-grid">${equipment2.map((rule) => `<div class="equipment-tile">${equipmentIcon(rule.type)}<span>${cardEscape(rule.type)}</span><b>× ${number5(rule.count)}</b></div>`).join("")}</div>` : '<p class="empty-line">当前品质暂无解锁装备</p>';
|
|
3697
3770
|
const perLevel = card.type === "血统道具" && card.level === 1;
|
|
3698
3771
|
const customAttributes = card.attributes.filter((attribute) => !classicIds.has(attribute.id));
|
|
3699
3772
|
const extraAttributes = customAttributes.length ? `<div class="bloodline-custom-attributes">${customAttributes.map((attribute) => cardStatRow(attribute.name?.trim() || attribute.id, signed(attribute.value), true)).join("")}</div>` : "";
|
|
@@ -4438,7 +4511,8 @@ async function renderUncached(ctx, card, leaderboard, itemCard, characterCard, e
|
|
|
4438
4511
|
}, "release");
|
|
4439
4512
|
try {
|
|
4440
4513
|
const work = /* @__PURE__ */ __name(async () => {
|
|
4441
|
-
const
|
|
4514
|
+
const encounterCard = companionCard?.kind === "monster" || companionCard?.kind === "boss";
|
|
4515
|
+
const remoteAddress = signinCard ? void 0 : titleCard ? titleCard.artworkUrl : bloodlineCard ? bloodlineCard.artworkUrl : equipmentCard ? equipmentCard.artworkUrl : companionCard ? encounterCard ? void 0 : companionCard.artworkUrl : characterCard ? characterCard.artworkUrl : itemCard ? itemCard.artworkUrl : leaderboard ? leaderboard.backgroundUrl : card?.artworkUrl;
|
|
4442
4516
|
const isEquipment = !signinCard && !titleCard && !bloodlineCard && Boolean(equipmentCard);
|
|
4443
4517
|
const isCharacter = !signinCard && !titleCard && !bloodlineCard && !equipmentCard && !companionCard && Boolean(characterCard);
|
|
4444
4518
|
const [remoteArt, fallbackArt, entryArtwork, characterAssets, header, signinAssets] = await Promise.all([
|
|
@@ -2,3 +2,4 @@
|
|
|
2
2
|
export declare const companionCornerDecoration = "<svg viewBox=\"0 0 180 180\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M7 156C9 84 17 23 94 9M17 124C31 81 47 59 87 40M41 69C57 45 75 31 121 26M48 43C72 26 89 20 143 19\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <path d=\"M15 112C-1 86 2 67 11 57c17 20 22 34 4 55ZM26 79C15 47 21 28 37 23c10 25 10 45-11 56ZM47 53C53 29 66 19 87 18c-5 20-17 32-40 35ZM79 32c19-15 35-20 56-13-12 13-31 19-56 13Z\" fill=\"currentColor\" opacity=\".6\"/>\n <path d=\"M14 133c-3-27 15-47 34-49-1 23-13 41-34 49ZM32 94c6-28 26-42 45-42-8 24-22 39-45 42ZM66 49c18-20 36-24 56-15-17 17-33 21-56 15Z\" fill=\"currentColor\" opacity=\".35\"/>\n <g transform=\"translate(39 39)\">\n <g fill=\"var(--flower)\" stroke=\"currentColor\" stroke-width=\"1.2\">\n <ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(72)\"/>\n <ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(144)\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(216)\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(288)\"/>\n </g><circle r=\"7\" fill=\"currentColor\"/><circle r=\"3\" fill=\"var(--flower)\"/>\n </g>\n <g transform=\"translate(12 109) scale(.48)\"><g fill=\"var(--flower)\" stroke=\"currentColor\" stroke-width=\"2\"><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(72)\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(144)\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(216)\"/><ellipse cx=\"0\" cy=\"-18\" rx=\"10\" ry=\"18\" transform=\"rotate(288)\"/></g><circle r=\"7\" fill=\"currentColor\"/></g>\n</svg>";
|
|
3
3
|
export declare const petPortraitPlaceholder: string;
|
|
4
4
|
export declare const followerPortraitPlaceholder: string;
|
|
5
|
+
export declare const bossCardDecoration = "<svg viewBox=\"0 0 160 64\" aria-hidden=\"true\"><path d=\"M31 49 23 17l32 20L80 5l25 32 32-20-8 32ZM31 55h98\" fill=\"currentColor\" opacity=\".7\"/><path d=\"M9 51 26 39M134 39l17 12M5 58l19-10m112 0 19 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/><circle cx=\"80\" cy=\"5\" r=\"4\" fill=\"currentColor\"/><circle cx=\"23\" cy=\"17\" r=\"3\" fill=\"currentColor\"/><circle cx=\"137\" cy=\"17\" r=\"3\" fill=\"currentColor\"/></svg>";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Flow layout keeps every bloodline and skill row visible in bot/editor cards. */
|
|
2
|
-
export declare const companionCardStyles = "\n*{box-sizing:border-box}body{margin:0;width:760px}#capture{width:760px;position:relative;overflow:hidden;font-family:\"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif}\n.companion-sheet{--ink:#594322;--subtle:#79715a;--accent:#b78328;--edge:#c7a66a;--light-edge:#fff2c8;--panel:#fffaf0;--panel-deep:#f1e5cc;--paper:#e8ce9c;--flower:#fff9dc;--track:#e3e7d8;--track-edge:#9fad94;--health:#69985c;--health-light:#a4c68d;--radar:#c79539;--radar-fill:#dcb35369;--radar-grid:#c8ba94;color:var(--ink);padding:22px;background:radial-gradient(ellipse at 5% 12%,#fff8dfb0,transparent 42%),radial-gradient(ellipse at 98% 79%,#fff5d8a6,transparent 44%),repeating-linear-gradient(115deg,#f6e7c94d 0 1px,transparent 1px 5px),linear-gradient(155deg,#d5b777,#f2dfb9 37%,#c7ac76)}\n.follower-theme{--ink:#e6e5dc;--subtle:#b7b7b2;--accent:#d3d3cf;--edge:#858585;--light-edge:#e5e5de;--panel:#242424;--panel-deep:#181818;--paper:#232323;--flower:#d6d6d0;--track:#353535;--track-edge:#7c7c7c;--health:#a3a3a0;--health-light:#d5d5cf;--radar:#e3e3dc;--radar-fill:#bdbdbd51;--radar-grid:#686868;background:radial-gradient(ellipse at 10% 9%,#9f9f9f40,transparent 43%),radial-gradient(ellipse at 94% 83%,#91919145,transparent 35%),repeating-linear-gradient(125deg,#dddddd07 0 1px,transparent 1px 5px),linear-gradient(155deg,#575757,#1e1e1e 37%,#4e4e4e)}\n.companion-main{display:grid;grid-template-columns:334px minmax(0,1fr);gap:14px;align-items:stretch;position:relative;z-index:1}.portrait-column{min-width:0;display:flex;flex-direction:column;gap:14px}\n.companion-panel{position:relative;border:2px solid var(--edge);border-radius:27px;background:radial-gradient(ellipse at 22% 0%,color-mix(in srgb,var(--light-edge) 20%,transparent),transparent 51%),linear-gradient(160deg,var(--panel),var(--panel-deep));box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 50%,transparent),0 2px 6px #32290f30;min-width:0}.companion-panel:before{content:\"\";position:absolute;inset:8px;border:1px solid color-mix(in srgb,var(--edge) 55%,transparent);border-radius:20px;pointer-events:none}.panel-corner{position:absolute;width:112px;height:112px;color:var(--edge);pointer-events:none;z-index:3}.panel-corner svg{width:100%;height:100%;display:block}.corner-tl{top:-14px;left:-14px}.corner-tr{top:-14px;right:-14px;transform:rotate(90deg)}.corner-bl{bottom:-14px;left:-14px;transform:rotate(-90deg)}.corner-br{bottom:-14px;right:-14px;transform:rotate(180deg)}\n.companion-portrait{padding:10px;border-radius:18px;flex:0 0 auto;background:linear-gradient(135deg,var(--light-edge),var(--edge) 28%,var(--light-edge) 55%,var(--edge))}.companion-portrait:before{inset:5px;border-radius:12px;border-color:var(--light-edge)}.portrait-window{height:448px;border:2px solid var(--edge);border-radius:9px;overflow:hidden;background:var(--paper)}.companion-artwork{display:block;width:100%;height:100%;object-fit:contain}.follower-theme .companion-artwork{filter:grayscale(1)}.companion-portrait .panel-corner{width:97px;height:97px}.portrait-placeholder,.companion-placeholder{height:100%;display:grid;place-items:center;color:var(--subtle);font:21px \"Microsoft YaHei\",sans-serif}\n.companion-description{font:16px/1.65 \"Microsoft YaHei\",sans-serif;overflow-wrap:anywhere;color:var(--subtle);margin:0 10px}.bloodline-panel{padding:10px 16px 17px;flex:1}.ornament-heading{display:flex;align-items:center;justify-content:center;gap:10px;margin:0 0 12px;font-size:25px;font-weight:700;letter-spacing:3px;line-height:1.3;color:var(--ink)}.ornament-heading:before,.ornament-heading:after{content:\"\";height:1px;flex:1;background:linear-gradient(90deg,transparent,var(--edge))}.ornament-heading:after{transform:rotate(180deg)}.heading-star{font-size:16px;color:var(--accent);letter-spacing:0}.bloodline-list{display:grid;gap:10px}.bloodline-row{display:grid;grid-template-columns:41px minmax(0,1fr) auto;align-items:center;gap:9px;padding:8px 10px;border:1px solid var(--edge);border-radius:7px;box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--edge) 13%,transparent);background:color-mix(in srgb,var(--panel) 55%,transparent)}.bloodline-crest{width:41px;height:41px;display:grid;place-items:center;border:1px solid var(--edge);background:var(--paper);border-radius:50%;font-family:\"Microsoft YaHei\",sans-serif;font-size:27px;color:var(--ink)}.bloodline-crest svg{width:29px;height:29px}.follower-theme .bloodline-crest{filter:grayscale(1)}.bloodline-name{font-size:21px;font-weight:700;line-height:1.4;overflow-wrap:anywhere}.bloodline-quality{min-width:34px;padding:4px 6px;text-align:center;border:1px solid var(--edge);border-radius:7px;background:var(--paper);font:26px/1 Georgia,\"Microsoft YaHei\",serif;color:var(--ink)}\n.companion-stats{padding:22px 19px 14px;display:flex;flex-direction:column}.companion-identity{text-align:center;padding:6px 0 0;min-width:0}.companion-name{font-size:47px;font-weight:700;letter-spacing:4px;line-height:1.15;overflow-wrap:anywhere;margin:0 0 3px;text-shadow:0 1px 0 color-mix(in srgb,var(--panel) 70%,transparent)}.companion-level{font:30px/1.4 Georgia,\"Microsoft YaHei\",serif;margin:0;color:var(--subtle);overflow-wrap:anywhere}.state-badge{margin:6px auto 0;width:max-content;max-width:100%;display:flex;align-items:center;gap:11px;padding:5px 17px;border:1px solid var(--edge);border-radius:18px;background:color-mix(in srgb,var(--accent) 13%,transparent);color:var(--ink);font-size:19px;line-height:1}.state-badge svg{width:17px;height:17px;fill:currentColor}.state-resting{color:var(--subtle)}.state-fallen{background:color-mix(in srgb,var(--subtle) 15%,transparent);color:var(--subtle)}.permanent-note{margin:6px 0 0;color:var(--subtle);font-size:17px;line-height:1.4;letter-spacing:1px}.companion-power-row{display:flex;align-items:center;gap:10px;margin:18px 0 17px;min-width:0}.power-icon{flex:0 0 46px;height:46px;display:grid;place-items:center;border-radius:50%;border:1px solid var(--edge);box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--panel) 75%,transparent);color:var(--accent);background:color-mix(in srgb,var(--accent) 13%,transparent)}.power-icon svg{width:29px;height:29px;stroke:currentColor;fill:currentColor;stroke-width:2;stroke-linejoin:round}.companion-power-label{font-size:21px;white-space:nowrap}.companion-power{min-width:0;flex:1;text-align:right;overflow-wrap:anywhere;font:38px/1.2 Georgia,\"Microsoft YaHei\",serif;color:var(--accent);letter-spacing:-1px}\n.companion-resource{font-family:\"Microsoft YaHei\",sans-serif;margin-bottom:15px}.resource-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:18px;color:var(--subtle);line-height:1.45}.resource-label{display:flex;align-items:center;gap:7px;font-weight:600;flex-shrink:0}.resource-label svg{width:20px;height:20px;fill:var(--health)}.resource-number{text-align:right;overflow-wrap:anywhere;min-width:0;font-size:17px}.resource-track{height:20px;position:relative;margin-top:7px;border:1px solid var(--track-edge);border-radius:11px;overflow:hidden;background:linear-gradient(var(--track),color-mix(in srgb,var(--track) 70%,var(--panel)));box-shadow:inset 0 1px 3px #30362030}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:10px;background:linear-gradient(var(--health-light),var(--health) 48%,color-mix(in srgb,var(--health) 75%,var(--health-light)));border-right:1px solid #fff8}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:12px/1 \"Microsoft YaHei\",sans-serif;color:#fffef7;text-shadow:0 1px 2px #37422d}.exp-resource .resource-heading{color:#63809b}.exp-resource .resource-label svg{fill:#6f95b3}.exp-resource .resource-track{border-color:#91adc0;background:#e2e9ed}.exp-resource .resource-fill{background:linear-gradient(#b5d9e5,#74a4c0 50%,#9bc5d6)}\n.companion-attributes{margin-top:3px;flex:1;display:flex;flex-direction:column;justify-content:center;min-width:0}.companion-attributes .ornament-heading{margin-bottom:4px;font-size:22px;gap:6px;letter-spacing:2px}.companion-radar{width:100%;height:300px;display:block;overflow:visible}.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.2}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.5;stroke-linejoin:round}.radar-dot{fill:var(--flower);stroke:var(--radar);stroke-width:2}.radar-label{font:18px \"Microsoft YaHei\",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,\"Microsoft YaHei\",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 \"Microsoft YaHei\",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 \"Microsoft YaHei\",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}\n.companion-skills{position:relative;z-index:1;padding:12px 18px 19px;margin-top:15px}.companion-skills .ornament-heading{margin-bottom:13px}.skill-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 13px}.companion-skill{position:relative;min-width:0;display:grid;grid-template-columns:47px minmax(0,1fr) auto;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--edge);border-radius:7px;box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--edge) 12%,transparent);background:color-mix(in srgb,var(--panel) 55%,transparent);min-height:65px}.skill-icon{width:47px;height:47px;border:1px solid var(--edge);border-radius:7px;display:grid;place-items:center;background:radial-gradient(ellipse at 40% 23%,color-mix(in srgb,var(--accent) 55%,var(--paper)),color-mix(in srgb,var(--paper) 72%,#282015));color:var(--flower);box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--light-edge) 20%,transparent)}.skill-icon svg{width:31px;height:31px;stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}.skill-name{font-size:20px;font-weight:700;overflow-wrap:anywhere;line-height:1.35}.skill-level{font:18px/1.2 Georgia,\"Microsoft YaHei\",serif;border:1px solid color-mix(in srgb,var(--edge) 55%,transparent);border-radius:13px;padding:5px 9px;white-space:nowrap;color:var(--ink);background:color-mix(in srgb,var(--accent) 9%,transparent)}.empty-list{margin:10px 0;color:var(--subtle);font:17px/1.6 \"Microsoft YaHei\",sans-serif;text-align:center}.follower-theme .companion-panel{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 50%,transparent),0 2px 6px #00000040}.follower-theme .skill-icon{background:radial-gradient(ellipse at 40% 23%,#858585,#292929)}.follower-theme .resource-track{box-shadow:inset 0 1px 3px #00000030}.follower-theme .companion-power{color:var(--ink)}.follower-theme .resource-percent{color:#fffef7;text-shadow:0 1px 2px #242725}\n.skill-icon,.bloodline-crest{position:relative;overflow:hidden}.bloodline-crest.has-entry-artwork{border-radius:7px}.skill-entry-artwork,.bloodline-entry-artwork{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;border-radius:inherit;background:var(--paper);z-index:1}.follower-theme .skill-entry-artwork,.follower-theme .bloodline-entry-artwork{filter:grayscale(1)}\n";
|
|
2
|
+
export declare const companionCardStyles = "\n*{box-sizing:border-box}body{margin:0;width:760px}#capture{width:760px;position:relative;overflow:hidden;font-family:\"KaiTi\",\"STKaiti\",\"Microsoft YaHei\",sans-serif}\n.companion-sheet{--ink:#594322;--subtle:#79715a;--accent:#b78328;--edge:#c7a66a;--light-edge:#fff2c8;--panel:#fffaf0;--panel-deep:#f1e5cc;--paper:#e8ce9c;--flower:#fff9dc;--track:#e3e7d8;--track-edge:#9fad94;--health:#69985c;--health-light:#a4c68d;--radar:#c79539;--radar-fill:#dcb35369;--radar-grid:#c8ba94;color:var(--ink);padding:22px;background:radial-gradient(ellipse at 5% 12%,#fff8dfb0,transparent 42%),radial-gradient(ellipse at 98% 79%,#fff5d8a6,transparent 44%),repeating-linear-gradient(115deg,#f6e7c94d 0 1px,transparent 1px 5px),linear-gradient(155deg,#d5b777,#f2dfb9 37%,#c7ac76)}\n.follower-theme{--ink:#e6e5dc;--subtle:#b7b7b2;--accent:#d3d3cf;--edge:#858585;--light-edge:#e5e5de;--panel:#242424;--panel-deep:#181818;--paper:#232323;--flower:#d6d6d0;--track:#353535;--track-edge:#7c7c7c;--health:#a3a3a0;--health-light:#d5d5cf;--radar:#e3e3dc;--radar-fill:#bdbdbd51;--radar-grid:#686868;background:radial-gradient(ellipse at 10% 9%,#9f9f9f40,transparent 43%),radial-gradient(ellipse at 94% 83%,#91919145,transparent 35%),repeating-linear-gradient(125deg,#dddddd07 0 1px,transparent 1px 5px),linear-gradient(155deg,#575757,#1e1e1e 37%,#4e4e4e)}\n.companion-main{display:grid;grid-template-columns:334px minmax(0,1fr);gap:14px;align-items:stretch;position:relative;z-index:1}.portrait-column{min-width:0;display:flex;flex-direction:column;gap:14px}\n.companion-panel{position:relative;border:2px solid var(--edge);border-radius:27px;background:radial-gradient(ellipse at 22% 0%,color-mix(in srgb,var(--light-edge) 20%,transparent),transparent 51%),linear-gradient(160deg,var(--panel),var(--panel-deep));box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 50%,transparent),0 2px 6px #32290f30;min-width:0}.companion-panel:before{content:\"\";position:absolute;inset:8px;border:1px solid color-mix(in srgb,var(--edge) 55%,transparent);border-radius:20px;pointer-events:none}.panel-corner{position:absolute;width:112px;height:112px;color:var(--edge);pointer-events:none;z-index:3}.panel-corner svg{width:100%;height:100%;display:block}.corner-tl{top:-14px;left:-14px}.corner-tr{top:-14px;right:-14px;transform:rotate(90deg)}.corner-bl{bottom:-14px;left:-14px;transform:rotate(-90deg)}.corner-br{bottom:-14px;right:-14px;transform:rotate(180deg)}\n.companion-portrait{padding:10px;border-radius:18px;flex:0 0 auto;background:linear-gradient(135deg,var(--light-edge),var(--edge) 28%,var(--light-edge) 55%,var(--edge))}.companion-portrait:before{inset:5px;border-radius:12px;border-color:var(--light-edge)}.portrait-window{height:448px;border:2px solid var(--edge);border-radius:9px;overflow:hidden;background:var(--paper)}.companion-artwork{display:block;width:100%;height:100%;object-fit:contain}.follower-theme .companion-artwork{filter:grayscale(1)}.companion-portrait .panel-corner{width:97px;height:97px}.portrait-placeholder,.companion-placeholder{height:100%;display:grid;place-items:center;color:var(--subtle);font:21px \"Microsoft YaHei\",sans-serif}\n.companion-description{font:16px/1.65 \"Microsoft YaHei\",sans-serif;overflow-wrap:anywhere;color:var(--subtle);margin:0 10px}.bloodline-panel{padding:10px 16px 17px;flex:1}.ornament-heading{display:flex;align-items:center;justify-content:center;gap:10px;margin:0 0 12px;font-size:25px;font-weight:700;letter-spacing:3px;line-height:1.3;color:var(--ink)}.ornament-heading:before,.ornament-heading:after{content:\"\";height:1px;flex:1;background:linear-gradient(90deg,transparent,var(--edge))}.ornament-heading:after{transform:rotate(180deg)}.heading-star{font-size:16px;color:var(--accent);letter-spacing:0}.bloodline-list{display:grid;gap:10px}.bloodline-row{display:grid;grid-template-columns:41px minmax(0,1fr) auto;align-items:center;gap:9px;padding:8px 10px;border:1px solid var(--edge);border-radius:7px;box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--edge) 13%,transparent);background:color-mix(in srgb,var(--panel) 55%,transparent)}.bloodline-crest{width:41px;height:41px;display:grid;place-items:center;border:1px solid var(--edge);background:var(--paper);border-radius:50%;font-family:\"Microsoft YaHei\",sans-serif;font-size:27px;color:var(--ink)}.bloodline-crest svg{width:29px;height:29px}.follower-theme .bloodline-crest{filter:grayscale(1)}.bloodline-name{font-size:21px;font-weight:700;line-height:1.4;overflow-wrap:anywhere}.bloodline-quality{min-width:34px;padding:4px 6px;text-align:center;border:1px solid var(--edge);border-radius:7px;background:var(--paper);font:26px/1 Georgia,\"Microsoft YaHei\",serif;color:var(--ink)}\n.companion-stats{padding:22px 19px 14px;display:flex;flex-direction:column}.companion-identity{text-align:center;padding:6px 0 0;min-width:0}.companion-name{font-size:47px;font-weight:700;letter-spacing:4px;line-height:1.15;overflow-wrap:anywhere;margin:0 0 3px;text-shadow:0 1px 0 color-mix(in srgb,var(--panel) 70%,transparent)}.companion-level{font:30px/1.4 Georgia,\"Microsoft YaHei\",serif;margin:0;color:var(--subtle);overflow-wrap:anywhere}.state-badge{margin:6px auto 0;width:max-content;max-width:100%;display:flex;align-items:center;gap:11px;padding:5px 17px;border:1px solid var(--edge);border-radius:18px;background:color-mix(in srgb,var(--accent) 13%,transparent);color:var(--ink);font-size:19px;line-height:1}.state-badge svg{width:17px;height:17px;fill:currentColor}.state-resting{color:var(--subtle)}.state-fallen{background:color-mix(in srgb,var(--subtle) 15%,transparent);color:var(--subtle)}.permanent-note{margin:6px 0 0;color:var(--subtle);font-size:17px;line-height:1.4;letter-spacing:1px}.companion-power-row{display:flex;align-items:center;gap:10px;margin:18px 0 17px;min-width:0}.power-icon{flex:0 0 46px;height:46px;display:grid;place-items:center;border-radius:50%;border:1px solid var(--edge);box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--panel) 75%,transparent);color:var(--accent);background:color-mix(in srgb,var(--accent) 13%,transparent)}.power-icon svg{width:29px;height:29px;stroke:currentColor;fill:currentColor;stroke-width:2;stroke-linejoin:round}.companion-power-label{font-size:21px;white-space:nowrap}.companion-power{min-width:0;flex:1;text-align:right;overflow-wrap:anywhere;font:38px/1.2 Georgia,\"Microsoft YaHei\",serif;color:var(--accent);letter-spacing:-1px}\n.companion-resource{font-family:\"Microsoft YaHei\",sans-serif;margin-bottom:15px}.resource-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:18px;color:var(--subtle);line-height:1.45}.resource-label{display:flex;align-items:center;gap:7px;font-weight:600;flex-shrink:0}.resource-label svg{width:20px;height:20px;fill:var(--health)}.resource-number{text-align:right;overflow-wrap:anywhere;min-width:0;font-size:17px}.resource-track{height:20px;position:relative;margin-top:7px;border:1px solid var(--track-edge);border-radius:11px;overflow:hidden;background:linear-gradient(var(--track),color-mix(in srgb,var(--track) 70%,var(--panel)));box-shadow:inset 0 1px 3px #30362030}.resource-fill{display:block;position:absolute;top:0;bottom:0;left:0;border-radius:10px;background:linear-gradient(var(--health-light),var(--health) 48%,color-mix(in srgb,var(--health) 75%,var(--health-light)));border-right:1px solid #fff8}.resource-percent{position:absolute;inset:0;display:grid;place-items:center;font:12px/1 \"Microsoft YaHei\",sans-serif;color:#fffef7;text-shadow:0 1px 2px #37422d}.exp-resource .resource-heading{color:#63809b}.exp-resource .resource-label svg{fill:#6f95b3}.exp-resource .resource-track{border-color:#91adc0;background:#e2e9ed}.exp-resource .resource-fill{background:linear-gradient(#b5d9e5,#74a4c0 50%,#9bc5d6)}\n.companion-attributes{margin-top:3px;flex:1;display:flex;flex-direction:column;justify-content:center;min-width:0}.companion-attributes .ornament-heading{margin-bottom:4px;font-size:22px;gap:6px;letter-spacing:2px}.companion-radar{width:100%;height:300px;display:block;overflow:visible}.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.2}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.5;stroke-linejoin:round}.radar-dot{fill:var(--flower);stroke:var(--radar);stroke-width:2}.radar-label{font:18px \"Microsoft YaHei\",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,\"Microsoft YaHei\",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 \"Microsoft YaHei\",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 \"Microsoft YaHei\",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}\n.companion-skills{position:relative;z-index:1;padding:12px 18px 19px;margin-top:15px}.companion-skills .ornament-heading{margin-bottom:13px}.skill-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 13px}.companion-skill{position:relative;min-width:0;display:grid;grid-template-columns:47px minmax(0,1fr) auto;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--edge);border-radius:7px;box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--edge) 12%,transparent);background:color-mix(in srgb,var(--panel) 55%,transparent);min-height:65px}.skill-icon{width:47px;height:47px;border:1px solid var(--edge);border-radius:7px;display:grid;place-items:center;background:radial-gradient(ellipse at 40% 23%,color-mix(in srgb,var(--accent) 55%,var(--paper)),color-mix(in srgb,var(--paper) 72%,#282015));color:var(--flower);box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--light-edge) 20%,transparent)}.skill-icon svg{width:31px;height:31px;stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}.skill-name{font-size:20px;font-weight:700;overflow-wrap:anywhere;line-height:1.35}.skill-level{font:18px/1.2 Georgia,\"Microsoft YaHei\",serif;border:1px solid color-mix(in srgb,var(--edge) 55%,transparent);border-radius:13px;padding:5px 9px;white-space:nowrap;color:var(--ink);background:color-mix(in srgb,var(--accent) 9%,transparent)}.empty-list{margin:10px 0;color:var(--subtle);font:17px/1.6 \"Microsoft YaHei\",sans-serif;text-align:center}.follower-theme .companion-panel{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 50%,transparent),0 2px 6px #00000040}.follower-theme .skill-icon{background:radial-gradient(ellipse at 40% 23%,#858585,#292929)}.follower-theme .resource-track{box-shadow:inset 0 1px 3px #00000030}.follower-theme .companion-power{color:var(--ink)}.follower-theme .resource-percent{color:#fffef7;text-shadow:0 1px 2px #242725}\n.skill-icon,.bloodline-crest{position:relative;overflow:hidden}.bloodline-crest.has-entry-artwork{border-radius:7px}.skill-entry-artwork,.bloodline-entry-artwork{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;border-radius:inherit;background:var(--paper);z-index:1}.follower-theme .skill-entry-artwork,.follower-theme .bloodline-entry-artwork{filter:grayscale(1)}\n.monster-theme{--ink:#e0eeea;--subtle:#a2b9b6;--accent:#9bd8c9;--edge:#668f90;--light-edge:#c3e5d7;--panel:#203f48;--panel-deep:#142d38;--paper:#183440;--flower:#d3efe6;--track:#213c46;--track-edge:#769b92;--health:#518f7f;--health-light:#96d6b5;--radar:#a2d8c9;--radar-fill:#7bb5ab55;--radar-grid:#507d80;background:radial-gradient(ellipse at 10% 9%,#81b8a840,transparent 43%),radial-gradient(ellipse at 94% 83%,#49808045,transparent 35%),repeating-linear-gradient(125deg,#d6eee608 0 1px,transparent 1px 5px),linear-gradient(155deg,#3c6269,#142a35 37%,#30515a)}\n.boss-theme{--ink:#f7e2c3;--subtle:#ceafac;--accent:#edc385;--edge:#b77c62;--light-edge:#f5dba4;--panel:#492937;--panel-deep:#281b2a;--paper:#342132;--flower:#ffe6b2;--track:#4b2837;--track-edge:#b88170;--health:#a24d59;--health-light:#eb9395;--radar:#edc385;--radar-fill:#daaa5b55;--radar-grid:#925c64;padding-top:55px;background:radial-gradient(ellipse at 48% 0%,#ecc07855,transparent 40%),radial-gradient(ellipse at 96% 83%,#c54a6245,transparent 35%),repeating-linear-gradient(125deg,#f2dfbd08 0 1px,transparent 1px 5px),linear-gradient(155deg,#773b46,#211b2c 37%,#5d2c42)}\n.boss-card-decoration{position:absolute;top:3px;left:50%;transform:translateX(-50%);width:160px;height:52px;color:var(--accent)}.boss-card-decoration svg{display:block;width:100%;height:100%}.boss-theme .companion-portrait,.boss-theme .companion-stats{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 60%,transparent),0 0 13px #daa04e40}.boss-theme .state-badge{border-radius:5px;letter-spacing:3px;background:linear-gradient(135deg,#b6805130,#8c44502b);padding:7px 15px}.monster-theme .state-badge{letter-spacing:2px}\n.enemy-equipment{padding:13px 18px 18px;margin-top:15px}.enemy-equipment-list{display:grid;gap:8px}.enemy-equipment-row{display:grid;grid-template-columns:28px minmax(0,1fr) auto auto;align-items:center;gap:10px;padding:8px 11px;border:1px solid var(--edge);border-radius:7px;background:color-mix(in srgb,var(--panel) 55%,transparent);min-width:0}.equipment-symbol{color:var(--accent);font-size:26px}.enemy-equipment-name{font-size:20px;line-height:1.4;overflow-wrap:anywhere}.enemy-equipment-name small{color:var(--accent);font:17px Georgia,serif;white-space:nowrap}.equipment-slot{font:15px/1.4 \"Microsoft YaHei\",sans-serif;color:var(--subtle);max-width:120px;overflow-wrap:anywhere}\n.enemy-main{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.enemy-sheet .companion-stats{justify-content:center;padding:24px 24px 26px}.enemy-sheet .companion-name{font-size:43px;letter-spacing:2px}.enemy-sheet .companion-power-row{margin:24px 0}.enemy-sheet .companion-resource{margin-bottom:0}.enemy-attributes{padding:16px 12px 12px;display:flex;align-items:center}.enemy-attributes .companion-attributes{margin:0}.enemy-sheet>.bloodline-panel{margin-top:15px;padding:13px 18px 18px}.enemy-sheet .bloodline-list{grid-template-columns:repeat(2,minmax(0,1fr))}.enemy-sheet .bloodline-name{font-size:20px}\n\n";
|
|
@@ -4,5 +4,5 @@ export interface CardEntryArtwork {
|
|
|
4
4
|
skills?: ReadonlyArray<string | undefined>;
|
|
5
5
|
bloodlines?: ReadonlyArray<string | undefined>;
|
|
6
6
|
}
|
|
7
|
-
/**
|
|
7
|
+
/** Pets/followers keep portraits; encounters show fixed combat data without disposable artwork. */
|
|
8
8
|
export declare function companionCardHtml(card: CompanionCardData, artwork?: string, icons?: CardEntryArtwork): string;
|
|
@@ -5,7 +5,7 @@ export interface ReqStatistics extends BaseRequest {
|
|
|
5
5
|
export interface ResStatistics extends BaseResponse {
|
|
6
6
|
/** 统计快照生成时间,Unix 毫秒。 */
|
|
7
7
|
generatedAt: number;
|
|
8
|
-
/**
|
|
8
|
+
/** 普通玩家最近游戏消息的在线窗口;处理指令可延续在线。 */
|
|
9
9
|
onlineWindowMs: number;
|
|
10
10
|
/** 服务端快照缓存时长。 */
|
|
11
11
|
cacheTtlMs: number;
|
|
@@ -83,7 +83,9 @@ export interface CharacterCardData {
|
|
|
83
83
|
}
|
|
84
84
|
export declare enum CompanionCardKind {
|
|
85
85
|
pet = "pet",
|
|
86
|
-
follower = "follower"
|
|
86
|
+
follower = "follower",
|
|
87
|
+
monster = "monster",
|
|
88
|
+
boss = "boss"
|
|
87
89
|
}
|
|
88
90
|
export declare enum CompanionCardState {
|
|
89
91
|
active = "active",
|
|
@@ -94,7 +96,7 @@ export declare enum CompanionSkillType {
|
|
|
94
96
|
active = "active",
|
|
95
97
|
passive = "passive"
|
|
96
98
|
}
|
|
97
|
-
/**
|
|
99
|
+
/** 伙伴与探索敌人的属性图片;探索详情读取本次已冻结的实际参战快照。 */
|
|
98
100
|
export interface CompanionCardData {
|
|
99
101
|
kind: CompanionCardKind;
|
|
100
102
|
/** 已保存形象的临时 HTTPS 链接;缺图时由客户端显示伙伴占位。 */
|
|
@@ -129,6 +131,14 @@ export interface CompanionCardData {
|
|
|
129
131
|
type?: CompanionSkillType;
|
|
130
132
|
artworkUrl?: string;
|
|
131
133
|
}>;
|
|
134
|
+
/** 本场怪物实际生效的装备;伙伴详情可省略。字段追加,保留既有协议编号。 */
|
|
135
|
+
equipment?: Array<{
|
|
136
|
+
id: string;
|
|
137
|
+
name: string;
|
|
138
|
+
quality: string;
|
|
139
|
+
slot: string;
|
|
140
|
+
enhancement?: number;
|
|
141
|
+
}>;
|
|
132
142
|
}
|
|
133
143
|
export interface ItemCardData {
|
|
134
144
|
artworkUrl?: string;
|
package/package.json
CHANGED
|
@@ -31,3 +31,5 @@ export const followerPortraitPlaceholder = image(`<svg xmlns="http://www.w3.org/
|
|
|
31
31
|
<g fill="#1d1d1d" stroke="#a7a7a7" stroke-width="2"><path d="M158 485c7-79 20-135 42-166 15-44 29-83 70-88 46 7 58 45 73 89 19 29 37 87 42 166Z"/><path d="M218 297c-4-50 14-87 52-88 39 1 58 38 52 89l-19-9-13-30-20-12-22 12-11 30Z"/><path d="m216 316 54 66 54-66M197 358l-26 117m172-117 27 117" fill="none"/><path d="m247 287 23 20 24-20-11 48h-26Z" fill="#808080" stroke="none"/></g>
|
|
32
32
|
<text x="270" y="551" text-anchor="middle" font-family="Microsoft YaHei,sans-serif" font-size="26" letter-spacing="4" fill="#e1e0d6">暂无随从形象</text>
|
|
33
33
|
</svg>`)
|
|
34
|
+
|
|
35
|
+
export const bossCardDecoration = '<svg viewBox="0 0 160 64" aria-hidden="true"><path d="M31 49 23 17l32 20L80 5l25 32 32-20-8 32ZM31 55h98" fill="currentColor" opacity=".7"/><path d="M9 51 26 39M134 39l17 12M5 58l19-10m112 0 19 10" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="80" cy="5" r="4" fill="currentColor"/><circle cx="23" cy="17" r="3" fill="currentColor"/><circle cx="137" cy="17" r="3" fill="currentColor"/></svg>'
|
|
@@ -12,4 +12,10 @@ export const companionCardStyles = `
|
|
|
12
12
|
.companion-attributes{margin-top:3px;flex:1;display:flex;flex-direction:column;justify-content:center;min-width:0}.companion-attributes .ornament-heading{margin-bottom:4px;font-size:22px;gap:6px;letter-spacing:2px}.companion-radar{width:100%;height:300px;display:block;overflow:visible}.radar-grid{fill:none;stroke:var(--radar-grid);stroke-width:1.2}.radar-axis{stroke:var(--radar-grid);stroke-width:1;opacity:.8}.radar-area{fill:var(--radar-fill);stroke:var(--radar);stroke-width:2.5;stroke-linejoin:round}.radar-dot{fill:var(--flower);stroke:var(--radar);stroke-width:2}.radar-label{font:18px "Microsoft YaHei",sans-serif;fill:var(--ink)}.radar-value{font:20px Georgia,"Microsoft YaHei",serif;fill:var(--ink)}.radar-scale{font:11px Georgia,serif;fill:var(--subtle)}.empty-attributes{padding:45px 10px;color:var(--subtle);font:18px/1.6 "Microsoft YaHei",sans-serif;text-align:center}.custom-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px 10px;margin:6px 0 0;font:15px/1.5 "Microsoft YaHei",sans-serif;color:var(--subtle)}.custom-attributes span{overflow-wrap:anywhere}.custom-attributes b{font-weight:500;color:var(--ink)}
|
|
13
13
|
.companion-skills{position:relative;z-index:1;padding:12px 18px 19px;margin-top:15px}.companion-skills .ornament-heading{margin-bottom:13px}.skill-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 13px}.companion-skill{position:relative;min-width:0;display:grid;grid-template-columns:47px minmax(0,1fr) auto;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--edge);border-radius:7px;box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--edge) 12%,transparent);background:color-mix(in srgb,var(--panel) 55%,transparent);min-height:65px}.skill-icon{width:47px;height:47px;border:1px solid var(--edge);border-radius:7px;display:grid;place-items:center;background:radial-gradient(ellipse at 40% 23%,color-mix(in srgb,var(--accent) 55%,var(--paper)),color-mix(in srgb,var(--paper) 72%,#282015));color:var(--flower);box-shadow:inset 0 0 0 3px color-mix(in srgb,var(--light-edge) 20%,transparent)}.skill-icon svg{width:31px;height:31px;stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}.skill-name{font-size:20px;font-weight:700;overflow-wrap:anywhere;line-height:1.35}.skill-level{font:18px/1.2 Georgia,"Microsoft YaHei",serif;border:1px solid color-mix(in srgb,var(--edge) 55%,transparent);border-radius:13px;padding:5px 9px;white-space:nowrap;color:var(--ink);background:color-mix(in srgb,var(--accent) 9%,transparent)}.empty-list{margin:10px 0;color:var(--subtle);font:17px/1.6 "Microsoft YaHei",sans-serif;text-align:center}.follower-theme .companion-panel{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 50%,transparent),0 2px 6px #00000040}.follower-theme .skill-icon{background:radial-gradient(ellipse at 40% 23%,#858585,#292929)}.follower-theme .resource-track{box-shadow:inset 0 1px 3px #00000030}.follower-theme .companion-power{color:var(--ink)}.follower-theme .resource-percent{color:#fffef7;text-shadow:0 1px 2px #242725}
|
|
14
14
|
.skill-icon,.bloodline-crest{position:relative;overflow:hidden}.bloodline-crest.has-entry-artwork{border-radius:7px}.skill-entry-artwork,.bloodline-entry-artwork{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;border-radius:inherit;background:var(--paper);z-index:1}.follower-theme .skill-entry-artwork,.follower-theme .bloodline-entry-artwork{filter:grayscale(1)}
|
|
15
|
+
.monster-theme{--ink:#e0eeea;--subtle:#a2b9b6;--accent:#9bd8c9;--edge:#668f90;--light-edge:#c3e5d7;--panel:#203f48;--panel-deep:#142d38;--paper:#183440;--flower:#d3efe6;--track:#213c46;--track-edge:#769b92;--health:#518f7f;--health-light:#96d6b5;--radar:#a2d8c9;--radar-fill:#7bb5ab55;--radar-grid:#507d80;background:radial-gradient(ellipse at 10% 9%,#81b8a840,transparent 43%),radial-gradient(ellipse at 94% 83%,#49808045,transparent 35%),repeating-linear-gradient(125deg,#d6eee608 0 1px,transparent 1px 5px),linear-gradient(155deg,#3c6269,#142a35 37%,#30515a)}
|
|
16
|
+
.boss-theme{--ink:#f7e2c3;--subtle:#ceafac;--accent:#edc385;--edge:#b77c62;--light-edge:#f5dba4;--panel:#492937;--panel-deep:#281b2a;--paper:#342132;--flower:#ffe6b2;--track:#4b2837;--track-edge:#b88170;--health:#a24d59;--health-light:#eb9395;--radar:#edc385;--radar-fill:#daaa5b55;--radar-grid:#925c64;padding-top:55px;background:radial-gradient(ellipse at 48% 0%,#ecc07855,transparent 40%),radial-gradient(ellipse at 96% 83%,#c54a6245,transparent 35%),repeating-linear-gradient(125deg,#f2dfbd08 0 1px,transparent 1px 5px),linear-gradient(155deg,#773b46,#211b2c 37%,#5d2c42)}
|
|
17
|
+
.boss-card-decoration{position:absolute;top:3px;left:50%;transform:translateX(-50%);width:160px;height:52px;color:var(--accent)}.boss-card-decoration svg{display:block;width:100%;height:100%}.boss-theme .companion-portrait,.boss-theme .companion-stats{box-shadow:inset 0 0 0 3px var(--panel),inset 0 0 0 4px color-mix(in srgb,var(--edge) 60%,transparent),0 0 13px #daa04e40}.boss-theme .state-badge{border-radius:5px;letter-spacing:3px;background:linear-gradient(135deg,#b6805130,#8c44502b);padding:7px 15px}.monster-theme .state-badge{letter-spacing:2px}
|
|
18
|
+
.enemy-equipment{padding:13px 18px 18px;margin-top:15px}.enemy-equipment-list{display:grid;gap:8px}.enemy-equipment-row{display:grid;grid-template-columns:28px minmax(0,1fr) auto auto;align-items:center;gap:10px;padding:8px 11px;border:1px solid var(--edge);border-radius:7px;background:color-mix(in srgb,var(--panel) 55%,transparent);min-width:0}.equipment-symbol{color:var(--accent);font-size:26px}.enemy-equipment-name{font-size:20px;line-height:1.4;overflow-wrap:anywhere}.enemy-equipment-name small{color:var(--accent);font:17px Georgia,serif;white-space:nowrap}.equipment-slot{font:15px/1.4 "Microsoft YaHei",sans-serif;color:var(--subtle);max-width:120px;overflow-wrap:anywhere}
|
|
19
|
+
.enemy-main{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.enemy-sheet .companion-stats{justify-content:center;padding:24px 24px 26px}.enemy-sheet .companion-name{font-size:43px;letter-spacing:2px}.enemy-sheet .companion-power-row{margin:24px 0}.enemy-sheet .companion-resource{margin-bottom:0}.enemy-attributes{padding:16px 12px 12px;display:flex;align-items:center}.enemy-attributes .companion-attributes{margin:0}.enemy-sheet>.bloodline-panel{margin-top:15px;padding:13px 18px 18px}.enemy-sheet .bloodline-list{grid-template-columns:repeat(2,minmax(0,1fr))}.enemy-sheet .bloodline-name{font-size:20px}
|
|
20
|
+
|
|
15
21
|
`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CompanionCardData } from '../shared/face'
|
|
2
2
|
import { cardEscape } from './detailCardTemplate'
|
|
3
3
|
import { companionCardStyles } from './companionCardStyles'
|
|
4
|
-
import { companionCornerDecoration, followerPortraitPlaceholder, petPortraitPlaceholder } from './companionCardAssets'
|
|
4
|
+
import { bossCardDecoration, companionCornerDecoration, followerPortraitPlaceholder, petPortraitPlaceholder } from './companionCardAssets'
|
|
5
5
|
|
|
6
6
|
/** Only renderer-loaded data URLs or editor-approved URLs, aligned with entry indices. */
|
|
7
7
|
export interface CardEntryArtwork {
|
|
@@ -69,20 +69,29 @@ function skills(card: CompanionCardData, icons?: CardEntryArtwork): string {
|
|
|
69
69
|
return `<section class="companion-panel companion-skills" aria-label="技能">${corners()}${heading('技能')}${card.skills.length ? `<div class="skill-grid">${card.skills.map((skill, index) => `<div class="companion-skill" data-skill-id="${cardEscape(skill.id)}"><span class="skill-icon" aria-hidden="true"><svg viewBox="0 0 36 36">${skill.type === 'passive' ? passive : active}</svg>${icons?.skills?.[index] ? `<img class="skill-entry-artwork" data-entry-index="${index}" src="${cardEscape(icons.skills[index])}" alt="">` : ''}</span><span class="skill-name">${cardEscape(skill.name)}</span><span class="skill-level">Lv.${number(skill.rank)}</span></div>`).join('')}</div>` : '<p class="empty-list">暂无技能</p>'}</section>`
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
function equipment(card: CompanionCardData): string {
|
|
73
|
+
if (!card.equipment) return ''
|
|
74
|
+
return `<section class="companion-panel enemy-equipment" aria-label="装备">${heading('装备')}${card.equipment.length ? '<div class="enemy-equipment-list">' + card.equipment.map(item => `<div class="enemy-equipment-row"><span class="equipment-symbol" aria-hidden="true">✧</span><span class="enemy-equipment-name">${cardEscape(item.name)}${item.enhancement ? ' <small>+' + number(item.enhancement) + '</small>' : ''}</span><span class="equipment-slot">${cardEscape(item.slot)}</span><span class="bloodline-quality">${cardEscape(item.quality)}</span></div>`).join('') + '</div>' : '<p class="empty-list">暂无装备</p>'}</section>`
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Pets/followers keep portraits; encounters show fixed combat data without disposable artwork. */
|
|
73
78
|
export function companionCardHtml(card: CompanionCardData, artwork?: string, icons?: CardEntryArtwork): string {
|
|
74
79
|
const pet = card.kind === 'pet'
|
|
80
|
+
const enemy = card.kind === 'monster' || card.kind === 'boss'
|
|
81
|
+
const boss = card.kind === 'boss'
|
|
82
|
+
const kind = enemy ? boss ? 'boss' : 'monster' : pet ? 'pet' : 'follower'
|
|
83
|
+
const typeName = enemy ? boss ? '首领' : '普通怪物' : pet ? '宠物' : '随从'
|
|
75
84
|
const fallback = pet ? petPortraitPlaceholder : followerPortraitPlaceholder
|
|
76
85
|
const healthPercent = ratio(card.hp, card.maxHp) * 100
|
|
77
86
|
const experience = Math.max(0, Math.min(100, finite(card.experiencePercent ?? 0)))
|
|
78
87
|
const state = pet ? card.state === 'fallen' ? 'fallen' : card.state === 'resting' ? 'resting' : 'active' : 'active'
|
|
79
|
-
const stateName = pet ? { active: '出战', resting: '休息', fallen: '倒下' }[state] : '自动参战'
|
|
80
|
-
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>${companionCardStyles}</style></head><body><main id="capture" class="companion-sheet ${
|
|
81
|
-
|
|
82
|
-
<section class="companion-panel companion-stats" aria-label="${
|
|
88
|
+
const stateName = enemy ? typeName : pet ? { active: '出战', resting: '休息', fallen: '倒下' }[state] : '自动参战'
|
|
89
|
+
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>${companionCardStyles}</style></head><body><main id="capture" class="companion-sheet ${kind}-theme${enemy ? ' enemy-sheet' : ''}" data-kind="${kind}">${boss ? `<div class="boss-card-decoration">${bossCardDecoration}</div>` : ''}<div class="companion-main${enemy ? ' enemy-main' : ''}">
|
|
90
|
+
${enemy ? '' : `<div class="portrait-column"><div class="companion-panel companion-portrait">${corners()}<div class="portrait-window"><img id="companion-image" class="companion-artwork" src="${cardEscape(artwork || fallback)}" data-fallback="${cardEscape(fallback)}" alt="${cardEscape(card.name)}的形象图"></div></div>${card.description?.trim() ? `<p class="companion-description">${cardEscape(card.description.trim())}</p>` : ''}${bloodlines(card, icons)}</div>`}
|
|
91
|
+
<section class="companion-panel companion-stats" aria-label="${typeName}属性">${corners(['tr', 'br'])}<div class="companion-identity"><h1 id="companion-name" class="companion-name">${cardEscape(card.name)}</h1><p class="companion-level">Lv. ${number(card.level)}</p><div class="state-badge state-${state}">${pet ? paw : '<span aria-hidden="true">✦</span>'}<span>${stateName}</span>${pet ? paw : '<span aria-hidden="true">✦</span>'}</div>${kind === 'follower' ? '<p class="permanent-note">战死后永久离队</p>' : ''}</div>
|
|
83
92
|
<div class="companion-power-row"><span class="power-icon" aria-hidden="true">${sword}</span><span class="companion-power-label">战力</span><strong id="companion-power" class="companion-power">${number(card.power)}</strong></div>
|
|
84
93
|
<div class="companion-resource hp-resource"><div class="resource-heading"><span class="resource-label"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="M16 28C6 21 2 17 2 10a7 7 0 0 1 14-2 7 7 0 0 1 14 2c0 7-4 11-14 18Z"/></svg>生命值</span><span id="companion-hp" class="resource-number">${number(card.hp)} / ${number(card.maxHp)}</span></div><div class="resource-track" role="progressbar" aria-label="生命值" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${healthPercent}"><span class="resource-fill" style="width:${healthPercent}%"></span><span class="resource-percent">${number(healthPercent)}%</span></div></div>
|
|
85
94
|
${pet ? `<div class="companion-resource exp-resource"><div class="resource-heading"><span class="resource-label"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="m16 2 4.5 9.1 10 1.4-7.3 7.1 1.7 10-8.9-4.7-8.9 4.7 1.7-10-7.3-7.1 10-1.4Z"/></svg>经验进度</span><span class="resource-number">${number(experience)}%</span></div><div class="resource-track" role="progressbar" aria-label="经验进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${experience}"><span class="resource-fill" style="width:${experience}%"></span><span class="resource-percent">${number(experience)}%</span></div></div>` : ''}
|
|
86
|
-
<section class="companion-attributes" aria-label="一级属性">${heading('一级属性')}${radar(card)}</section></section>
|
|
87
|
-
</div>${skills(card, icons)}</main></body></html>`
|
|
95
|
+
${enemy ? '</section><section class="companion-panel enemy-attributes">' : ''}<section class="companion-attributes" aria-label="一级属性">${heading('一级属性')}${radar(card)}</section></section>
|
|
96
|
+
</div>${enemy ? bloodlines(card, icons) : ''}${skills(card, icons)}${equipment(card)}</main></body></html>`
|
|
88
97
|
}
|
package/src/plugin/skillCard.ts
CHANGED
|
@@ -135,7 +135,8 @@ async function renderUncached(ctx: Context, card?: SkillCardData, leaderboard?:
|
|
|
135
135
|
const release = () => { const next = waiting.shift(); if (next) next(); else running-- }
|
|
136
136
|
try {
|
|
137
137
|
const work = async () => {
|
|
138
|
-
const
|
|
138
|
+
const encounterCard = companionCard?.kind === 'monster' || companionCard?.kind === 'boss'
|
|
139
|
+
const remoteAddress = signinCard ? undefined : titleCard ? titleCard.artworkUrl : bloodlineCard ? bloodlineCard.artworkUrl : equipmentCard ? equipmentCard.artworkUrl : companionCard ? encounterCard ? undefined : companionCard.artworkUrl : characterCard ? characterCard.artworkUrl : itemCard ? itemCard.artworkUrl : leaderboard ? leaderboard.backgroundUrl : card?.artworkUrl
|
|
139
140
|
const isEquipment = !signinCard && !titleCard && !bloodlineCard && Boolean(equipmentCard)
|
|
140
141
|
const isCharacter = !signinCard && !titleCard && !bloodlineCard && !equipmentCard && !companionCard && Boolean(characterCard)
|
|
141
142
|
// Download independent artwork and open the browser together. A cold portrait
|
|
@@ -6,7 +6,7 @@ export interface ReqStatistics extends BaseRequest {}
|
|
|
6
6
|
export interface ResStatistics extends BaseResponse {
|
|
7
7
|
/** 统计快照生成时间,Unix 毫秒。 */
|
|
8
8
|
generatedAt: number;
|
|
9
|
-
/**
|
|
9
|
+
/** 普通玩家最近游戏消息的在线窗口;处理指令可延续在线。 */
|
|
10
10
|
onlineWindowMs: number;
|
|
11
11
|
/** 服务端快照缓存时长。 */
|
|
12
12
|
cacheTtlMs: number;
|
|
@@ -25,7 +25,7 @@ export interface ServiceType {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export const serviceProto: ServiceProto<ServiceType> = {
|
|
28
|
-
"version":
|
|
28
|
+
"version": 42,
|
|
29
29
|
"services": [
|
|
30
30
|
{
|
|
31
31
|
"id": 0,
|
|
@@ -1786,6 +1786,55 @@ export const serviceProto: ServiceProto<ServiceType> = {
|
|
|
1786
1786
|
]
|
|
1787
1787
|
}
|
|
1788
1788
|
}
|
|
1789
|
+
},
|
|
1790
|
+
{
|
|
1791
|
+
"id": 14,
|
|
1792
|
+
"name": "equipment",
|
|
1793
|
+
"type": {
|
|
1794
|
+
"type": "Array",
|
|
1795
|
+
"elementType": {
|
|
1796
|
+
"type": "Interface",
|
|
1797
|
+
"properties": [
|
|
1798
|
+
{
|
|
1799
|
+
"id": 0,
|
|
1800
|
+
"name": "id",
|
|
1801
|
+
"type": {
|
|
1802
|
+
"type": "String"
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
1805
|
+
{
|
|
1806
|
+
"id": 1,
|
|
1807
|
+
"name": "name",
|
|
1808
|
+
"type": {
|
|
1809
|
+
"type": "String"
|
|
1810
|
+
}
|
|
1811
|
+
},
|
|
1812
|
+
{
|
|
1813
|
+
"id": 2,
|
|
1814
|
+
"name": "quality",
|
|
1815
|
+
"type": {
|
|
1816
|
+
"type": "String"
|
|
1817
|
+
}
|
|
1818
|
+
},
|
|
1819
|
+
{
|
|
1820
|
+
"id": 3,
|
|
1821
|
+
"name": "slot",
|
|
1822
|
+
"type": {
|
|
1823
|
+
"type": "String"
|
|
1824
|
+
}
|
|
1825
|
+
},
|
|
1826
|
+
{
|
|
1827
|
+
"id": 4,
|
|
1828
|
+
"name": "enhancement",
|
|
1829
|
+
"type": {
|
|
1830
|
+
"type": "Number"
|
|
1831
|
+
},
|
|
1832
|
+
"optional": true
|
|
1833
|
+
}
|
|
1834
|
+
]
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
"optional": true
|
|
1789
1838
|
}
|
|
1790
1839
|
]
|
|
1791
1840
|
},
|
|
@@ -1799,6 +1848,14 @@ export const serviceProto: ServiceProto<ServiceType> = {
|
|
|
1799
1848
|
{
|
|
1800
1849
|
"id": 1,
|
|
1801
1850
|
"value": "follower"
|
|
1851
|
+
},
|
|
1852
|
+
{
|
|
1853
|
+
"id": 2,
|
|
1854
|
+
"value": "monster"
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
"id": 3,
|
|
1858
|
+
"value": "boss"
|
|
1802
1859
|
}
|
|
1803
1860
|
]
|
|
1804
1861
|
},
|
package/src/shared/face/index.ts
CHANGED
|
@@ -52,6 +52,8 @@ export interface CharacterCardData {
|
|
|
52
52
|
export enum CompanionCardKind {
|
|
53
53
|
pet = 'pet',
|
|
54
54
|
follower = 'follower',
|
|
55
|
+
monster = 'monster',
|
|
56
|
+
boss = 'boss',
|
|
55
57
|
}
|
|
56
58
|
export enum CompanionCardState {
|
|
57
59
|
active = 'active',
|
|
@@ -62,7 +64,7 @@ export enum CompanionSkillType {
|
|
|
62
64
|
active = 'active',
|
|
63
65
|
passive = 'passive',
|
|
64
66
|
}
|
|
65
|
-
/**
|
|
67
|
+
/** 伙伴与探索敌人的属性图片;探索详情读取本次已冻结的实际参战快照。 */
|
|
66
68
|
export interface CompanionCardData {
|
|
67
69
|
kind: CompanionCardKind;
|
|
68
70
|
/** 已保存形象的临时 HTTPS 链接;缺图时由客户端显示伙伴占位。 */
|
|
@@ -81,6 +83,8 @@ export interface CompanionCardData {
|
|
|
81
83
|
attributes: Array<{ id: string; name: string; value: number }>;
|
|
82
84
|
bloodlines: Array<{ name: string; quality: string; emoji?: string; artworkUrl?: string }>;
|
|
83
85
|
skills: Array<{ id: string; name: string; rank: number; quality?: string; type?: CompanionSkillType; artworkUrl?: string }>;
|
|
86
|
+
/** 本场怪物实际生效的装备;伙伴详情可省略。字段追加,保留既有协议编号。 */
|
|
87
|
+
equipment?: Array<{ id: string; name: string; quality: string; slot: string; enhancement?: number }>;
|
|
84
88
|
}
|
|
85
89
|
export interface ItemCardData {
|
|
86
90
|
artworkUrl?: string;
|