Files
noname-shuying/mengsan/relics/rooms.js
T
2026-10-08 23:46:57 +08:00

57 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { heldRelics, relicDefinitions, canAcquireRelic, grantRelic } from "./definitions.js";
import { relicState, healRun, changeMaxHp, grantGold, upgradeCards } from "./progression.js";
import { relicRandomGet } from "./random.js";
export const restRecovery = run => 8+heldRelics(run).reduce((n,r)=>n+(r.rule.restHeal || 0),0);
export const relicShopPrice = (run,base) => Math.max(1,Math.floor(heldRelics(run).reduce((n,r)=>n*(r.rule.shopDiscount || 1),base)));
export function recordRelicShopPurchase(run){relicState(run).mawBankBroken=true;}
export function relicRestChoices(run) {
const state=relicState(run),choices=[];
for(const relic of heldRelics(run)){
const action=relic.rule.restAction;
if(action==="dig")choices.push({id:"dig",name:"挖掘",description:"获得一件可实现的随机普通、罕见或稀有遗物"});
if(action==="lift")choices.push({id:"lift",name:"举重",description:`以后每场战斗获得额外力量(${state.giryaLevels || 0}/3)`,disabled:(state.giryaLevels || 0)>=3});
if(action==="rekindle")choices.push({id:"rekindle",name:"添火",description:"让南瓜蜡烛再次燃烧5场战斗",disabled:(state.candleRemaining || 0)>=5});
if(action==="cook")choices.push({id:"cook",name:"烹饪",description:"最大生命+5;梦三适配值"});
}
return choices;
}
export function applyRoomRelics(run,node,action) {
const receipt=`${run.actIndex}:${node.type}:${node.id}:${action}`,state=relicState(run);
const receipts=run.player.relicRoomReceipts ||= [];
if(receipts.includes(receipt))return null;
const relics=heldRelics(run),before=run.player.hp;
if(action==="enter"){
if(node.type==="shop")for(const relic of relics)healRun(run,relic.rule.shopHeal || 0);
if(node.type==="rest"){
state.afterRest=true;
for(const relic of relics)healRun(run,Math.floor(run.player.deck.length/5)*(relic.rule.restEntryHealPerFive || 0));
}
if(node.type==="event")for(const relic of relics)healRun(run,relic.rule.eventHeal || 0);
} else if(node.type==="rest"){
if(action==="heal"){
healRun(run,restRecovery(run));
for(const relic of relics){const r=relic.rule;if(r.restMaxHp)changeMaxHp(run,r.restMaxHp);if(r.restCardChoice)(state.choices ||= []).push({relic:relic.name,kind:"cardReward",count:1,offerCount:3});}
} else if(action==="upgrade")upgradeCards(run,1);
else if(action==="lift" && relics.some(r=>r.rule.restAction==="lift") && (state.giryaLevels || 0)<3)state.giryaLevels=(state.giryaLevels || 0)+1;
else if(action==="rekindle" && relics.some(r=>r.rule.restAction==="rekindle"))state.candleRemaining=5;
else if(action==="cook" && relics.some(r=>r.rule.restAction==="cook"))changeMaxHp(run,5);
else if(action==="dig" && relics.some(r=>r.rule.restAction==="dig")){
const candidates=Object.values(relicDefinitions).filter(r=>["普通","罕见","稀有"].includes(r.tier) && canAcquireRelic(run,r.id));
const relic=relicRandomGet(run,candidates);if(relic)grantRelic(run,relic.id);
} else return null;
} else return null;
run.player.relicRoomReceipts.push(receipt); return {recovered:run.player.hp-before,relics};
}
// Arrival precedes purchases and combat; retries on the same in-memory node
// cannot pay again. Battle rollback retains the existing checkpoint semantics.
export function applyRelicNodeEnter(run,node) {
if(!node || node.completed)return;
const state=relicState(run);
const key=`${run.actIndex}:${node.id}`;
const receipts=state.nodeReceipts ||= [];
if(receipts.includes(key))return;
receipts.push(key);
for(const relic of heldRelics(run))if(relic.rule.nodeGold && !state.mawBankBroken)grantGold(run,relic.rule.nodeGold);
}