feat # 继续补全遗物系统

This commit is contained in:
2026-10-08 23:46:57 +08:00
parent 623f53a1d2
commit 1c93c77f4f
335 changed files with 11528 additions and 1797 deletions
+2
View File
@@ -1,5 +1,6 @@
import { ui } from "../../../../noname.js";
import { mountMenu } from "./navigation.js";
import { createRelicIcon } from "./relic-icon.js";
export const chooseButtons = (title, choices, description = "", options = {}) => new Promise(resolve => {
const previousFocus = document.activeElement;
@@ -33,6 +34,7 @@ export const chooseButtons = (title, choices, description = "", options = {}) =>
button.type = "button";
button.className = "mengsan-choice-shuying";
button.dataset.choice = choice.id;
const icon=createRelicIcon(choice.image);if(icon){button.classList.add("has-relic-image");button.appendChild(icon);}
if (choice.danger) button.classList.add("danger");
const name = document.createElement("span");
name.className = "mengsan-choice-name-shuying";
+3 -1
View File
@@ -3,6 +3,7 @@ import { askMenu, openModeSelection, openNonameMenu } from "../navigation.js";
import { ui, get } from "../../../../../noname.js";
import config from "../../config.js";
import { getRelic } from "../../relics/definitions.js";
import { createRelicIcon } from "../relic-icon.js";
import { renderBonds } from "../bonds.js";
import { getSelectableNodes } from "../../progression/state.js";
@@ -269,8 +270,9 @@ export const showMap = (run, { saveRun } = {}) => new Promise(resolve => {
values.forEach(value => {
const row = ui.create.div(".mengsan-map-inventory-row-shuying", list);
const relic = getRelic(value);
const icon=createRelicIcon(relic?.image);if(icon)row.appendChild(icon);
createText("", relic?.name || get.translation(value) || value, row);
createText("", relic?.description || "已获得", row);
createText("", relic ? `${relic.pool} · ${relic.tier}${relic.ancient ? ` · ${relic.ancient}` : ""}:${relic.description}${relic.implementation==="pending" ? `(${relic.implementationNote})` : ""}` : "已获得", row);
});
};
const supports = run.player.supports || [];
+11
View File
@@ -0,0 +1,11 @@
import { lib } from "../../../../noname.js";
export function relicImageURL(image) {
return typeof image==="string" && /^extension\/术樱包\/mengsan\/assets\/relics\/[a-z0-9_]+\.png$/.test(image) ? (lib.assetURL || "")+image : null;
}
export function createRelicIcon(image) {
const src=relicImageURL(image);if(!src)return null;
const icon=document.createElement("img");
icon.className="mengsan-relic-icon-shuying";icon.src=src;icon.alt="";
icon.setAttribute("aria-hidden","true");icon.width=48;icon.height=48;icon.loading="lazy";
icon.addEventListener("error",()=>icon.remove(),{once:true});return icon;
}
+3 -1
View File
@@ -1,5 +1,6 @@
import { ui } from "../../../../noname.js";
import { heldRelics } from "../relics/definitions.js";
import { createRelicIcon } from "./relic-icon.js";
export function mountRelics(session, run, battleRelics) {
let dialog = null, list = null, previousFocus = null, disposed = false;
@@ -29,12 +30,13 @@ export function mountRelics(session, run, battleRelics) {
}
for (const relic of relics) {
const row = document.createElement("section");
const icon=createRelicIcon(relic.image);if(icon)row.appendChild(icon);
const name = document.createElement("h3");
name.textContent = relic.name;
const description = document.createElement("p");
description.textContent = relic.description;
const status = document.createElement("small");
status.textContent = battleRelics.status(relic);
status.textContent = `${relic.pool} · ${relic.tier}${relic.ancient ? ` · ${relic.ancient}` : ""} · ${battleRelics.status(relic)}`;
row.append(name, description, status);
list.appendChild(row);
}
+5 -2
View File
@@ -2,6 +2,7 @@ import { lib, get } from "../../../../noname.js";
import { cardCost } from "../battle/combat-rules.js";
import { cardUpgradeRule } from "../cards/upgrades.js";
import { getRelic } from "../relics/definitions.js";
import { relicImageURL, createRelicIcon } from "./relic-icon.js";
import { getCardRarity, applyCardRarity } from "../cards/rarity.js";
import { cleanCardDescription } from "../cards/description.js";
@@ -69,7 +70,7 @@ export function chooseRelicDialog(choices, options = {}) {
...options,
}, choice => {
const relic = getRelic(choice.relic);
return { name: relic.name, type: "遗物", image: null, cost: null,
return { name: relic.name, type: `${relic.tier} · ${relic.pool}${relic.ancient ? ` · ${relic.ancient}` : ""}`, image: relicImageURL(relic.image), cost: null,
description: relic.description };
});
}
@@ -85,7 +86,7 @@ function chooseRewardDialog(choices) {
if (isCardReward(choice)) return viewCard(choice);
const relic = getRelic(choice.relic);
return { name: relic?.name || choice.name, type: relic ? "遗物" : "奖励",
image: null, cost: null,
image: relicImageURL(relic?.image), cost: null,
description: plainText(relic?.description || choice.description) };
});
}
@@ -119,6 +120,7 @@ function chooseTilesDialog(choices, {
const view = viewChoice(choice);
if (describeChoice) view.description = describeChoice(choice);
const card = element("button", "mengsan-card-choice-tile-shuying", null, cards);
if(getRelic(choice.relic))card.classList.add("mengsan-relic-choice-tile-shuying");
card.type = "button";
if (view.rarity) applyCardRarity(card, cardNameOf(choice));
card.setAttribute("aria-label", `${view.name},${view.type}${view.rarity ? `,稀有度:${view.rarity.label}` : ""},${view.description}。${actionLabel}`);
@@ -177,6 +179,7 @@ export function chooseVictoryOptions(options, {
// Read-only loot list: inspecting a reward must not select or award it.
for (const reward of rewardItems) {
const item = element("p", "mengsan-victory-option-copy-shuying", null, board);
const icon=createRelicIcon(getRelic(reward.relic)?.image);if(icon)item.appendChild(icon);
element("strong", "", reward.name || reward.id, item);
if (reward.description) element("small", "", plainText(reward.description), item);
}
+7
View File
@@ -1385,6 +1385,13 @@ body.mengsan-battle-ui-shuying :is(
.mengsan-relic-list-shuying h3 { margin: 0 0 8px; color: #ffe0a1; }
.mengsan-relic-list-shuying p { margin: 0 0 6px; line-height: 1.7; }
.mengsan-relic-list-shuying small { color: #d1bd9c; }
.mengsan-relic-icon-shuying { position: relative !important; width: 48px; height: 48px; flex: none; object-fit: contain; }
.mengsan-relic-list-shuying section > .mengsan-relic-icon-shuying { float: left; margin: 0 14px 8px 0; }
.mengsan-choice-shuying.has-relic-image { position: relative; padding-left: 76px; }
.mengsan-choice-shuying.has-relic-image > .mengsan-relic-icon-shuying { position: absolute !important; left: 14px; top: 50%; transform: translateY(-50%); }
.mengsan-map-inventory-row-shuying > .mengsan-relic-icon-shuying { width: 40px; height: 40px; }
.mengsan-relic-choice-tile-shuying .mengsan-card-choice-art-shuying img { padding: 14px; box-sizing: border-box; background: transparent; }
.mengsan-relic-choice-tile-shuying .mengsan-card-choice-art-shuying:has(img) .mengsan-card-choice-glyph-shuying { display: none; }
@media (max-height: 500px) {
.mengsan-battle-relics-button-shuying { top: 122px; }
}