mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-20 22:29:59 +08:00
feat # 继续补全遗物系统
This commit is contained in:
@@ -1,99 +1,73 @@
|
||||
const entries = [
|
||||
{ id: "mengsan_burning_blood_shuying", name: "燃烧之血",
|
||||
description: "战斗结束后回复6点生命,不能超过生命上限。",
|
||||
effect: "battleHeal", amount: 6 },
|
||||
{ id: "mengsan_snake_ring_shuying", name: "蛇之戒指",
|
||||
description: "每场战斗开始时,额外摸2张牌。",
|
||||
effect: "openingDraw", amount: 2 },
|
||||
{ id: "mengsan_long_snake_ring_shuying", name: "长蛇戒指",
|
||||
description: "每场战斗的前3个自身回合开始时,额外摸2张牌。",
|
||||
effect: "earlyTurnDraw", amount: 2, turns: 3 },
|
||||
{ id: "mengsan_millennium_puzzle_shuying", name: "千年积木",
|
||||
description: "每场战斗首次实际损失生命且仍存活时,摸3张牌。",
|
||||
effect: "firstHpLossDraw", amount: 3 },
|
||||
{ id: "mengsan_pendulum_shuying", name: "摆动球",
|
||||
description: "每场战斗每到第3个自身回合开始时,额外摸1张牌。",
|
||||
effect: "periodicTurnDraw", amount: 1, turns: 3 },
|
||||
{ id: "mengsan_hand_charm_shuying", name: "束带",
|
||||
description: "基础手牌上限额外+1;重复获得不叠加。",
|
||||
effect: "handLimit", amount: 1 },
|
||||
{ id: "mengsan_meal_ticket_shuying", name: "餐券",
|
||||
description: "进入商店房间时回复15点生命。",
|
||||
effect: "shopHeal", amount: 15 },
|
||||
{ id: "mengsan_strawberry_shuying", name: "草莓",
|
||||
description: "获得时最大生命值提升7;不额外回复生命。",
|
||||
effect: "gainMaxHp", amount: 7 },
|
||||
{ id: "mengsan_bag_of_marbles_shuying", name: "弹珠袋",
|
||||
description: "每场战斗开始时给予所有敌人1层易伤。",
|
||||
effect: "openingVulnerable", amount: 1 },
|
||||
{ id: "mengsan_lantern_shuying", name: "灯笼",
|
||||
description: "每场战斗首个自身回合额外获得1点临时费用。",
|
||||
effect: "firstTurnEnergy", amount: 1 },
|
||||
{ id: "mengsan_red_mask_shuying", name: "红面具",
|
||||
description: "每场战斗开始时给予所有敌人1层虚弱。",
|
||||
effect: "openingWeak", amount: 1 },
|
||||
{ id: "mengsan_regal_pillow_shuying", name: "皇家枕头",
|
||||
description: "选择休息回血时额外回复15点生命。",
|
||||
effect: "restHeal", amount: 15 },
|
||||
{ id: "mengsan_festive_poppers_shuying", name: "节日拉炮",
|
||||
description: "每场战斗开始时对所有敌人造成9点伤害。",
|
||||
effect: "openingDamage", amount: 9 },
|
||||
{ id: "mengsan_vajra_shuying", name: "金刚杵",
|
||||
description: "每场战斗开始时获得1点力量。",
|
||||
effect: "openingStrength", amount: 1 },
|
||||
];
|
||||
import { relicCatalog } from "./catalog.js";
|
||||
import { relicRules, missingMechanisms, unhandledRelicRule } from "./rules.js";
|
||||
import { applyRelicPickup, relicCardRequirements } from "./progression.js";
|
||||
|
||||
export const relicDefinitions = Object.freeze(Object.fromEntries(
|
||||
entries.map(entry => [entry.id, Object.freeze({ ...entry,
|
||||
owner: null, image: null })])));
|
||||
|
||||
export const getRelic = id => Object.hasOwn(relicDefinitions, id)
|
||||
? relicDefinitions[id] : null;
|
||||
|
||||
export const heldRelics = run => [...new Set(run?.player?.items || [])]
|
||||
.map(getRelic).filter(Boolean);
|
||||
|
||||
export function canAcquireRelic(run, id) {
|
||||
export const relicAdaptations = Object.freeze({
|
||||
the_courier:"梦三商店出售【杀】、回复生命及三件随机遗物;购买后补货,折扣适用现有商品。药水尚无接口。遗物基价120金币,为梦三配置值。",
|
||||
miniature_tent:"每个休息选项可各选择一次,直至选择离开;不允许无限重复同一选项。",
|
||||
meat_cleaver:"网页没有烹饪细则;暂定每次烹饪最大生命+5,待用户确认。",
|
||||
big_mushroom:"沿用梦三初始手牌4张,扣减2张;未改成STS2的基础手牌数量。",
|
||||
ring_of_the_drake:"刘备仅映射铁甲战士池;其他角色池需配置player.relicPool才可获取。效果按前三个自身回合各摸2张接入。",
|
||||
runic_pyramid:"梦三原本按手牌上限弃牌;这里让全部手牌不计入弃牌上限。虚无牌照常消耗。",
|
||||
precarious_shears:"选牌后扣除16点生命;当前地图流程保留至少1点生命,待补充非战斗死亡结算。",
|
||||
fragrant_mushroom:"随机强化2张并扣除15点生命;当前地图流程保留至少1点生命,待补充非战斗死亡结算。",
|
||||
dusty_tome:"从已登记的先古事件牌池随机获得一张;网页未列出完整候选排除规则。",
|
||||
sword_of_stone:"按5次精英战胜利计数,变化为玉之剑;尚无精英单位的独立击杀标签。",
|
||||
paper_phrog:"依梦三易伤口径向上取整;作用于玩家发起的攻击,保留既有卡牌的额外易伤增幅。",
|
||||
paper_krane:"依梦三虚弱口径向下取整,敌人攻击倍率0.6。",
|
||||
maw_bank:"将进入一个新的梦三节点视为攀爬一层,先发12金币,再进行商店购买或战斗;原作楼层与额外剧情节点未单独区分。",
|
||||
});
|
||||
const entries = relicCatalog.map(item => {
|
||||
const rule = relicRules[item.wikiId];
|
||||
const missingCards = rule ? relicCardRequirements(rule) : [];
|
||||
const unhandled = rule ? unhandledRelicRule(rule) : [];
|
||||
const reason = missingMechanisms[item.wikiId] || (missingCards.length ? `尚缺网页对应卡牌:${missingCards.join("、")}` : !rule ? "尚未接入此效果" : unhandled.length ? `尚缺效果接口:${unhandled.join("、")}` : null);
|
||||
return Object.freeze({ ...item, owner: null, rule: rule || Object.freeze({}),
|
||||
implementation: reason ? "pending" : relicAdaptations[item.wikiId] ? "adapted" : "implemented",
|
||||
implementationNote: reason || relicAdaptations[item.wikiId] || "效果已接入,实机验收待完成。", effect: "sts2" });
|
||||
});
|
||||
entries.push(Object.freeze({ id: "mengsan_hand_charm_shuying", wikiId: "legacy_hand_charm",
|
||||
name: "束带", description: "基础手牌上限额外+1;重复获得不叠加。", pool: "通用", tier: "梦三道具",
|
||||
ancient: null, owner: null, image: null, effect: "handLimit", amount: 1,
|
||||
rule: Object.freeze({ handLimit: 1 }), implementation: "implemented", implementationNote: "保留原梦三道具。" }));
|
||||
export const relicDefinitions = Object.freeze(Object.fromEntries(entries.map(entry => [entry.id, entry])));
|
||||
const aliases = Object.freeze(Object.fromEntries(entries.flatMap(entry => [[entry.id, entry.id], [entry.wikiId, entry.id], [`mengsan_${entry.wikiId}_shuying`, entry.id]])));
|
||||
export const getRelic = id => Object.hasOwn(aliases, id) ? relicDefinitions[aliases[id]] : null;
|
||||
export const heldRelics = run => [...new Set((run?.player?.items || []).map(id => getRelic(id)?.id).filter(Boolean))].map(getRelic);
|
||||
export const relicPoolFor = run => run?.player?.relicPool || (run?.player?.character === "mengsan_liubei_shuying" ? "铁甲战士" : null);
|
||||
export function canAcquireRelic(run, id, { allowPending = false } = {}) {
|
||||
const relic = getRelic(id);
|
||||
return Boolean(run?.player && relic &&
|
||||
(relic.owner === null || relic.owner === run.player.character) &&
|
||||
!run.player.items?.includes(id));
|
||||
if (!run?.player || !relic || !allowPending && relic.implementation === "pending") return false;
|
||||
if (relic.pool !== "通用" && relic.pool !== relicPoolFor(run)) return false;
|
||||
return !heldRelics(run).some(item => item.id === relic.id || item.rule.replaces === relic.wikiId);
|
||||
}
|
||||
|
||||
export function grantRelic(run, id) {
|
||||
if (!getRelic(id)) throw new Error(`梦三遗物未注册:${id}`);
|
||||
if (!canAcquireRelic(run, id)) return false;
|
||||
const relic = getRelic(id);
|
||||
run.player.items ||= [];
|
||||
run.player.items.push(id);
|
||||
if (relic.effect === "handLimit") {
|
||||
run.player.handLimitBonus = (run.player.handLimitBonus || 0) +
|
||||
relic.amount;
|
||||
}
|
||||
if (relic.effect === "gainMaxHp") {
|
||||
if (Number.isFinite(run.player.maxHp)) {
|
||||
run.player.maxHp += relic.amount;
|
||||
} else {
|
||||
run.player.pendingRelicMaxHp =
|
||||
(run.player.pendingRelicMaxHp || 0) + relic.amount;
|
||||
}
|
||||
}
|
||||
if (!relic) throw new Error(`梦三遗物未注册:${id}`);
|
||||
if (!canAcquireRelic(run, id)) return false;
|
||||
const draft = JSON.parse(JSON.stringify(run));
|
||||
draft.player.items ||= [];
|
||||
if (relic.rule.replaces) draft.player.items = draft.player.items.filter(value => getRelic(value)?.wikiId !== relic.rule.replaces);
|
||||
draft.player.items.push(relic.id);
|
||||
applyRelicPickup(draft, relic, { entries, canAcquire: canAcquireRelic, grant: grantRelic });
|
||||
Object.assign(run, draft);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function initializeRelicMaxHp(run) {
|
||||
const amount = run.player.pendingRelicMaxHp || 0;
|
||||
if (!amount || !Number.isFinite(run.player.maxHp)) return;
|
||||
run.player.maxHp += amount;
|
||||
if (!Number.isFinite(run.player.maxHp)) return;
|
||||
run.player.maxHp = Math.max(1, run.player.maxHp + amount);
|
||||
delete run.player.pendingRelicMaxHp;
|
||||
run.player.hp = Math.min(run.player.hp, run.player.maxHp);
|
||||
if (run.player.pendingRelicFullHeal) { run.player.hp = run.player.maxHp; delete run.player.pendingRelicFullHeal; }
|
||||
}
|
||||
|
||||
export const relicRewardIds = entries.filter(entry =>
|
||||
entry.effect !== "handLimit").map(entry => `shared.reward.relic.${entry.id}`);
|
||||
|
||||
export const relicRewards = Object.fromEntries(relicRewardIds.map(id => {
|
||||
const relicId = id.slice("shared.reward.relic.".length);
|
||||
const relic = getRelic(relicId);
|
||||
return [id, { relic: relicId, name: `遗物·${relic.name}`,
|
||||
description: relic.description }];
|
||||
}));
|
||||
export const relicRewardIds = entries.filter(entry => entry.implementation !== "pending" && ["普通", "罕见", "稀有"].includes(entry.tier)).map(entry => `shared.reward.relic.${entry.id}`);
|
||||
export const relicShopRewardIds = entries.filter(entry => entry.implementation !== "pending" && ["普通", "罕见", "稀有", "商店"].includes(entry.tier)).map(entry => `shared.reward.relic.${entry.id}`);
|
||||
export const relicRewards = Object.fromEntries(entries.map(relic => [`shared.reward.relic.${relic.id}`, { relic: relic.id, name: `遗物·${relic.name}`, description: relic.description, image: relic.image }]));
|
||||
const ancientKeys={"涅奥":"neow","欧洛巴斯":"orobas","佩尔":"pael","特兹卡塔拉":"tezcatara","诺奴佩普":"nonupep","坦克斯":"tanx","瓦库":"vakuu","达弗":"darv"};
|
||||
export const relicRewardPools={
|
||||
"shared.pool.relic.shop":[...relicShopRewardIds],
|
||||
"shared.pool.relic.event":entries.filter(r=>r.implementation!=="pending" && r.tier==="事件").map(r=>`shared.reward.relic.${r.id}`),
|
||||
"shared.pool.relic.initial":entries.filter(r=>r.implementation!=="pending" && r.tier==="初始").map(r=>`shared.reward.relic.${r.id}`),
|
||||
...Object.fromEntries(Object.entries(ancientKeys).map(([ancient,key])=>[`shared.pool.relic.ancient.${key}`,entries.filter(r=>r.implementation!=="pending" && r.ancient===ancient).map(r=>`shared.reward.relic.${r.id}`)])),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user