mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-13 12:30:05 +08:00
fixed # 更新刘备配置和奖励
This commit is contained in:
@@ -12,6 +12,14 @@
|
||||
| 千年积木 | `mengsan_millennium_puzzle_shuying` | `millennium_puzzle.png` | 待提供 |
|
||||
| 摆动球 | `mengsan_pendulum_shuying` | `pendulum.png` | 待提供 |
|
||||
| 束带(既有道具) | `mengsan_hand_charm_shuying` | `hand_charm.png` | 待提供 |
|
||||
| 餐券 | `mengsan_meal_ticket_shuying` | `meal_ticket.png` | 待提供 |
|
||||
| 草莓 | `mengsan_strawberry_shuying` | `strawberry.png` | 待提供 |
|
||||
| 弹珠袋 | `mengsan_bag_of_marbles_shuying` | `bag_of_marbles.png` | 待提供 |
|
||||
| 灯笼 | `mengsan_lantern_shuying` | `lantern.png` | 待提供 |
|
||||
| 红面具 | `mengsan_red_mask_shuying` | `red_mask.png` | 待提供 |
|
||||
| 皇家枕头 | `mengsan_regal_pillow_shuying` | `regal_pillow.png` | 待提供 |
|
||||
| 节日拉炮 | `mengsan_festive_poppers_shuying` | `festive_poppers.png` | 待提供 |
|
||||
| 金刚杵 | `mengsan_vajra_shuying` | `vajra.png` | 待提供 |
|
||||
|
||||
建议使用统一尺寸的透明背景 PNG,实际尺寸和视觉风格在资源制作时确定。
|
||||
图片仅负责外观,不承载名称、效果或触发计数。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 梦三遗物(道具)
|
||||
|
||||
本目录负责遗物定义、持有规则与战斗效果管理。
|
||||
已实现五件新遗物,并接入既有“束带”。图片暂缺,清单见 [ASSETS.md](ASSETS.md)。
|
||||
已实现十三件新遗物,并接入既有“束带”。图片暂缺,清单见 [ASSETS.md](ASSETS.md)。
|
||||
|
||||
## 已实现的遗物
|
||||
|
||||
@@ -13,6 +13,22 @@
|
||||
| 千年积木 | 每场战斗首次实际生命减少且仍存活时摸 3 张;纯护甲损失不触发 |
|
||||
| 摆动球 | 每场战斗第 3、6、9……个自身回合开始额外摸 1 张 |
|
||||
| 束带 | 原有手牌上限 +1,重复获得不叠加 |
|
||||
| 餐券 | 进入商店时回复 15 点生命,每个商店节点一次 |
|
||||
| 草莓 | 获得时生命上限 +7,当前生命不变,重复获得不叠加 |
|
||||
| 弹珠袋 | 开战时给予当时所有存活敌人 1 层易伤 |
|
||||
| 灯笼 | 首个自身回合可用费用 +1,费用上限不变,下回合恢复正常 |
|
||||
| 红面具 | 开战时给予当时所有存活敌人 1 层虚弱 |
|
||||
| 皇家枕头 | 选择休息回血时额外恢复 15;现有基础 8,总计 23 |
|
||||
| 节日拉炮 | 开战时对当时所有存活敌人造成 9 点伤害 |
|
||||
| 金刚杵 | 开战时获得 1 点力量,只在当前战斗有效 |
|
||||
|
||||
虚弱使攻击伤害减少 25%(向下取整),自身回合结束减少 1 层;
|
||||
力量使玩家攻击牌伤害增加对应点数,意图攻击沿用原有力量/虚弱计算。
|
||||
节日拉炮是非卡牌伤害,正常消耗目标护甲,不享受力量、易伤、虚弱的攻击修正。
|
||||
开场效果先摸牌和施加状态,再结算节日拉炮;仅影响开战时的敌人,不影响后续援军。
|
||||
餐券在打开商店前保存回血和节点记录,读档不会重复触发;
|
||||
皇家枕头不影响磨砺、商店治疗或其他回复效果。所有回复均不超过生命上限。
|
||||
草莓若在角色生命尚未初始化时获得,会保存待应用加成,初始化后只应用一次。
|
||||
|
||||
遗物互相独立:同时持有两种戒指时,开场和前三回合效果分别触发。
|
||||
所有回合计数按玩家自身实际开始的回合计算,不计敌方和支援回合,
|
||||
@@ -21,7 +37,7 @@
|
||||
|
||||
### 获得、保存和查看
|
||||
|
||||
- 五件新遗物加入共享 Boss 奖励池及第一章宝箱奖励池;
|
||||
- 新遗物通过自动生成的遗物奖励列表加入共享 Boss 和第一章宝箱奖励池;
|
||||
后续章节使用共享 Boss 奖励池的宝箱也可出现它们。
|
||||
- 角色默认不携带新遗物;未新增商店价格或精英掉落规则。
|
||||
- 持有记录沿用 `run.player.items`,已持有遗物会从随机奖励中排除。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { heldRelics } from "./definitions.js";
|
||||
|
||||
export function createRelicBattle(run, { active, draw, log }) {
|
||||
export function createRelicBattle(run, { active, draw, log, effect }) {
|
||||
const relics = heldRelics(run);
|
||||
let started = false, turns = 0, firstLoss = false;
|
||||
let openingHandBonus = 0, pendingHpDraw = null;
|
||||
@@ -24,6 +24,15 @@ export function createRelicBattle(run, { active, draw, log }) {
|
||||
for (const relic of relics) {
|
||||
if (relic.effect === "openingDraw") await drawEffect(relic);
|
||||
}
|
||||
for (const relic of relics.filter(item =>
|
||||
["openingVulnerable", "openingWeak", "openingStrength",
|
||||
"openingDamage"].includes(item.effect))
|
||||
.sort((a, b) => Number(a.effect === "openingDamage") -
|
||||
Number(b.effect === "openingDamage"))) {
|
||||
if (!usable()) break;
|
||||
log(relic, relic.description);
|
||||
await effect(relic);
|
||||
}
|
||||
if (pendingHpDraw) {
|
||||
const relic = pendingHpDraw;
|
||||
pendingHpDraw = null;
|
||||
@@ -35,6 +44,11 @@ export function createRelicBattle(run, { active, draw, log }) {
|
||||
seenTurns.add(event);
|
||||
turns++;
|
||||
for (const relic of relics) {
|
||||
if (relic.effect === "firstTurnEnergy" && turns === 1 &&
|
||||
usable()) {
|
||||
log(relic, `获得${relic.amount}点临时费用`);
|
||||
await effect(relic);
|
||||
}
|
||||
if ((relic.effect === "earlyTurnDraw" &&
|
||||
turns <= relic.turns) ||
|
||||
(relic.effect === "periodicTurnDraw" &&
|
||||
@@ -63,9 +77,12 @@ export function createRelicBattle(run, { active, draw, log }) {
|
||||
if (relic.effect === "periodicTurnDraw") {
|
||||
return `回合计数:${turns % relic.turns}/${relic.turns}`;
|
||||
}
|
||||
if (relic.effect === "openingDraw") {
|
||||
if (relic.effect.startsWith("opening")) {
|
||||
return started ? "本场已触发" : "等待战斗开始";
|
||||
}
|
||||
if (relic.effect === "firstTurnEnergy") {
|
||||
return turns ? "本场已触发" : "等待首个自身回合";
|
||||
}
|
||||
return "持续持有";
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
export function createOpeningEffects(game, owner, refreshEnergy) {
|
||||
const enemies = () => game.players.filter(player =>
|
||||
player !== owner && player.isAlive() &&
|
||||
player.storage?.mengsanCamp_shuying === "enemy");
|
||||
const addStatus = (player, key, skill, amount) => {
|
||||
player.storage[key] = (player.storage[key] || 0) + amount;
|
||||
player.addSkill(skill);
|
||||
player.markSkill(skill);
|
||||
};
|
||||
return async relic => {
|
||||
if (relic.effect === "firstTurnEnergy") {
|
||||
owner.storage.mengsanEnergy_shuying += relic.amount;
|
||||
refreshEnergy();
|
||||
} else if (relic.effect === "openingStrength") {
|
||||
addStatus(owner, "mengsanStrength_shuying",
|
||||
"mengsan_raider_strength_shuying", relic.amount);
|
||||
} else {
|
||||
for (const target of enemies()) {
|
||||
if (!owner.isAlive()) break;
|
||||
if (!target.isAlive()) continue;
|
||||
if (relic.effect === "openingVulnerable") {
|
||||
addStatus(target, "mengsanVulnerable_shuying",
|
||||
"mengsan_vulnerable_shuying", relic.amount);
|
||||
} else if (relic.effect === "openingWeak") {
|
||||
addStatus(target, "mengsanWeak_shuying",
|
||||
"mengsan_weak_shuying", relic.amount);
|
||||
} else if (relic.effect === "openingDamage") {
|
||||
const damage = target.damage(relic.amount, owner, "nocard");
|
||||
damage.mengsanScriptedSkill_shuying = true;
|
||||
await damage;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createRelicCombatSkills(getBattle, getOwner) {
|
||||
return {
|
||||
mengsan_relic_attack_shuying: {
|
||||
trigger: { global: "damageBegin1" },
|
||||
forced: true, silent: true, popup: false, priority: 80,
|
||||
filter(event) {
|
||||
const source = event.source;
|
||||
return Boolean(getBattle()?.session.active && event.card &&
|
||||
!event.mengsanScriptedSkill_shuying &&
|
||||
((source === getOwner() &&
|
||||
source?.storage?.mengsanStrength_shuying > 0) ||
|
||||
source?.storage?.mengsanWeak_shuying > 0));
|
||||
},
|
||||
async content(event, trigger) {
|
||||
const source = trigger.source;
|
||||
if (source === getOwner()) {
|
||||
trigger.num += source.storage.mengsanStrength_shuying || 0;
|
||||
}
|
||||
if (source.storage.mengsanWeak_shuying > 0) {
|
||||
trigger.num = Math.floor(trigger.num * 0.75);
|
||||
}
|
||||
},
|
||||
},
|
||||
mengsan_weak_shuying: {
|
||||
mark: true, marktext: "弱",
|
||||
onremove(player) { delete player.storage.mengsanWeak_shuying; },
|
||||
intro: { content(storage, player) {
|
||||
return `剩余${player.storage.mengsanWeak_shuying || 0}回合:` +
|
||||
"攻击伤害减少25%(向下取整)";
|
||||
} },
|
||||
trigger: { player: "phaseAfter" },
|
||||
forced: true, silent: true, popup: false,
|
||||
async content(event, trigger, player) {
|
||||
player.storage.mengsanWeak_shuying = Math.max(0,
|
||||
(player.storage.mengsanWeak_shuying || 0) - 1);
|
||||
if (player.storage.mengsanWeak_shuying) {
|
||||
player.markSkill("mengsan_weak_shuying");
|
||||
} else player.removeSkill("mengsan_weak_shuying");
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -17,6 +17,30 @@ const entries = [
|
||||
{ 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 },
|
||||
];
|
||||
|
||||
export const relicDefinitions = Object.freeze(Object.fromEntries(
|
||||
@@ -39,16 +63,31 @@ export function canAcquireRelic(run, id) {
|
||||
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);
|
||||
const relic = getRelic(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;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function initializeRelicMaxHp(run) {
|
||||
const amount = run.player.pendingRelicMaxHp || 0;
|
||||
if (!amount || !Number.isFinite(run.player.maxHp)) return;
|
||||
run.player.maxHp += amount;
|
||||
delete run.player.pendingRelicMaxHp;
|
||||
}
|
||||
|
||||
export const relicRewardIds = entries.filter(entry =>
|
||||
entry.effect !== "handLimit").map(entry => `shared.reward.relic.${entry.id}`);
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { heldRelics } from "./definitions.js";
|
||||
|
||||
export const restRecovery = run => 8 + heldRelics(run)
|
||||
.filter(relic => relic.effect === "restHeal")
|
||||
.reduce((sum, relic) => sum + relic.amount, 0);
|
||||
|
||||
export function applyRoomRelics(run, node, action) {
|
||||
const resting = node.type === "rest" && action === "heal";
|
||||
if (node.type !== "shop" && !resting) return null;
|
||||
const receipt = `${node.type}:${node.id}`;
|
||||
const receipts = run.player.relicRoomReceipts || [];
|
||||
if (receipts.includes(receipt)) return null;
|
||||
const effect = resting ? "restHeal" : "shopHeal";
|
||||
const relics = heldRelics(run).filter(relic => relic.effect === effect);
|
||||
const amount = (resting ? 8 : 0) + relics.reduce((sum, relic) =>
|
||||
sum + relic.amount, 0);
|
||||
if (!amount) return null;
|
||||
const before = run.player.hp;
|
||||
run.player.hp = Math.min(run.player.maxHp, before + amount);
|
||||
run.player.relicRoomReceipts = [...receipts, receipt];
|
||||
return { recovered: run.player.hp - before, relics };
|
||||
}
|
||||
Reference in New Issue
Block a user