fixed # 更改个人HUD

This commit is contained in:
2026-10-23 00:38:05 +08:00
parent fe3ebcc0e8
commit 727f469e93
89 changed files with 1692 additions and 59 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# 角色牌组
当前铁甲战士主表 94 张:新增 67 张、沿用 27 张;另有衍生牌【巨石】。专属牌归刘备,基础打击/痛击分别沿用杀/重杀。所有正常获得入口沿用 `canAcquireCard` 的角色检查。杀、重杀保留原有通用牌归属,并纳入刘备的随机生成牌池。旧存档的独立打击/痛击转换为杀/重杀,保留实例ID、强化和词缀;待结算候选保留原ID以避免冲突。
当前刘备主表 94 张:新增 67 张、沿用 27 张;另有衍生牌【巨石】。专属牌归刘备,基础打击/痛击分别沿用杀/重杀。所有正常获得入口沿用 `canAcquireCard` 的角色检查。杀、重杀保留原有通用牌归属,并纳入刘备的随机生成牌池。旧存档的独立打击/痛击转换为杀/重杀,保留实例ID、强化和词缀;待结算候选保留原ID以避免冲突。
| 目录/文件 | 职责 |
| --- | --- |
+5 -2
View File
@@ -36,6 +36,8 @@ const originalOf = event => {
return use?.mengsanIcRepeatOriginal_shuying || use?.cards?.find(c=>c.name===use.card?.name) || event.card;
};
import { bindCombatStatusSource } from "../../../battle/status-sources.js";
export function createAdvancedIronclad({game,get,lib,status,getBattle,battleEnergy,random}) {
const states=new WeakMap(), uses=new WeakMap(), hits=new WeakMap(), growth=new WeakMap();
const seenUses=new WeakSet(), seenBlocks=new WeakSet(), seenDraws=new WeakSet();
@@ -78,6 +80,7 @@ export function createAdvancedIronclad({game,get,lib,status,getBattle,battleEner
s={player,token,powers:Object.create(null),turn:Object.create(null),queue:[],flushing:false,
autoQueue:[],autoBusy:false,freeCards:new WeakSet(),negativeStrength:0,autoCount:0};
states.set(player,s); player.addSkill(MARK);
bindCombatStatusSource(player,token.session,"ironclad-advanced",()=>stateOf(player));
token.session.ownResource(s,()=>{if(states.get(player)===s){states.delete(player);player.removeSkill(MARK);s.queue.length=0;s.autoQueue.length=0;}});
bindIroncladHooks(player,token.session,{
valid:()=>valid(player,token),
@@ -444,7 +447,7 @@ export function createAdvancedIronclad({game,get,lib,status,getBattle,battleEner
if(r.attackDiscount)parts.push("本回合每打出一张攻击牌,费用减少1。");
if(r.draw)parts.push(`抽${r.draw}张牌。`);
if(r.stopDraw)parts.push("本回合不能再抽牌。");
if(r.generateAttack)parts.push("随机生成一张铁甲战士攻击牌至手牌,本回合费用为0。");
if(r.generateAttack)parts.push("随机生成一张刘备攻击牌至手牌,本回合费用为0。");
if(r.exhaustEnergy)parts.push(`被消耗时获得${r.exhaustEnergy}费用。`);
if(r.energyPerAttack)parts.push("每张攻击手牌获得1费用。");
if(r.stopEnergy)parts.push("本回合不能再获得费用。");
@@ -461,7 +464,7 @@ export function createAdvancedIronclad({game,get,lib,status,getBattle,battleEner
if(r.topPlays)parts.push(`免费打出抽牌堆顶的X${r.xBonus?"+1":""}张牌。`);
if(r.transformAttacks)parts.push(`所有攻击手牌变为巨石${r.boulderUpgrade?"+":""},仅本场战斗。`);
if(r.doubleTap)parts.push(`本回合接下来的${r.doubleTap}张攻击牌额外打出一次。`);
if(r.stoke)parts.push(`消耗所有手牌,每张随机生成一张${r.generatedUpgrade?"已强化":""}铁甲战士或无色牌至手牌。`);
if(r.stoke)parts.push(`消耗所有手牌,每张随机生成一张${r.generatedUpgrade?"已强化":""}刘备或无色牌至手牌。`);
if(r.retrieveAttack)parts.push("自身回合开始,从弃牌堆随机获得一张攻击牌并强化。");
if(r.bodyguard)parts.push("你承受敌人双倍伤害,敌人对其他友方的伤害减半。");
if(r.autoStrike)parts.push("抽到【杀】或名称含“打击”的攻击牌时,免费向随机敌人打出。");
+1 -1
View File
@@ -1,4 +1,4 @@
// 2026-10-03 灰机Wiki铁甲战士详情页主表;所有值均为当前状态。
// 2026-10-03 灰机Wiki卡牌详情页主表;本作品中归刘备专属牌组。
// 纯数据模块可被费用、升级、注册表及运行时共同导入,不依赖引擎。
import { ironcladAdvancedEntries } from "./advanced-data.js";
import { liubeiCardTraits } from "./traits.js";
+6 -4
View File
@@ -4,6 +4,7 @@ import { canPayCard, cardCost, isActiveCardUse } from "../../../battle/combat-ru
import { isAttackCard } from "../../../monsters/vine-tangled.js";
import { applyMengsanDebuff } from "../../../monsters/artifact-status.js";
import { createAdvancedIronclad } from "./advanced.js";
import { bindCombatStatusSource } from "../../../battle/status-sources.js";
const POWER_SKILL = "mengsan_ic_powers_shuying";
const belongsTo = (event, root) => {
@@ -42,12 +43,13 @@ export function createIroncladRuntime({ game, get, lib, status, getBattle, handE
player.removeSkill(POWER_SKILL);
});
states.set(player, s);
bindCombatStatusSource(player, token.session, "ironclad", () => stateOf(player));
player.addSkill(POWER_SKILL);
return s;
};
const add = (object, key, n) => {
const next = (object[key] || 0) + n;
if (!Number.isFinite(next) || next < 0 || next > Number.MAX_SAFE_INTEGER) throw new RangeError("铁甲战士效果数值越界");
if (!Number.isFinite(next) || next < 0 || next > Number.MAX_SAFE_INTEGER) throw new RangeError("刘备效果数值越界");
object[key] = next;
};
const strength = (player, n, token) => {
@@ -77,7 +79,7 @@ export function createIroncladRuntime({ game, get, lib, status, getBattle, handE
};
const exhaustHands = async (player, event, token, filter = () => true, afterEach = null) => {
const pile = pileOf(player, token);
if (typeof pile?.exhaustFromHand !== "function") throw new Error("铁甲战士缺少个人消耗接口");
if (typeof pile?.exhaustFromHand !== "function") throw new Error("刘备缺少个人消耗接口");
const playing = new Set(event.cards || []);
const cards = player.getCards("h").filter(c => !playing.has(c) && filter(c));
let count = 0;
@@ -191,7 +193,7 @@ export function createIroncladRuntime({ game, get, lib, status, getBattle, handE
if (r.hitsPerExhaust) hits = await exhaustHands(player, event, token);
else if (r.vulnerableHits && target.storage?.mengsanVulnerable_shuying > 0) hits = r.vulnerableHits;
const amount = (r.damage || 0) + (r.perExhaust ? r.perExhaust * exhaustCount(player, token) : 0);
if (!positive(amount) || !positive(hits)) throw new RangeError("铁甲战士攻击数值越界");
if (!positive(amount) || !positive(hits)) throw new RangeError("刘备攻击数值越界");
if (amount > 0) for (let i = 0; i < hits && valid(player, token); i++) {
const targets = r.all ? [...token.battle.players].filter(p => p !== player && p.isAlive() && player.isEnemyOf(p)) : [target];
for (const t of targets) {
@@ -260,7 +262,7 @@ export function createIroncladRuntime({ game, get, lib, status, getBattle, handE
mark: true, marktext: "战",
intro: { content(storage, player) {
const s = stateOf(player);
if (!s) return "本场战斗的铁甲战士效果";
if (!s) return "本场战斗的刘备效果";
const names = { turnStrength: "每回合力量", turnEnergy: "每回合费用", turnBlock: "每回合格挡", turnLoseHp: "披风每回合失血", infernoLoseHp: "狱火每回合失血", lossDamage: "失血全体伤害", lossStrength: "失血获得力量", vulnerableBonus: "易伤倍率加成", attackBlock: "攻击获得格挡", retaliation: "反击伤害", colossus: "巨像减伤" };
return Object.entries({ ...s.powers, ...s.turn, ...s.defense }).map(([k, v]) => `${names[k] || k}:${v === true ? "50%" : k === "vulnerableBonus" ? `${v * 100}%` : v}`).join("<br>");
} },
+2
View File
@@ -13,6 +13,7 @@ import { applyMengsanDebuff, consumeArtifact } from "../../../monsters/artifact-
import { isStunned } from "../../../battle/stun-intent.js";
import { canPayCard, isActiveCardUse, authorizeFreeCardUse, takeXCardUse, cardCost } from "../../../battle/combat-rules.js";
import { grantGold } from "../../../relics/progression.js";
import { bindCombatStatusSource } from "../../../battle/status-sources.js";
const BRIDGE="mengsan_shared_bridge_shuying", RULES="mengsan_shared_rules_shuying", END="mengsan_shared_end_shuying", LIMIT="mengsan_shared_limit_shuying", AFTER="mengsan_shared_after_shuying";
const safe=n=>Number.isSafeInteger(n) && n>=0;
@@ -51,6 +52,7 @@ export function createSharedCardRuntime({game,get,lib,status,getBattle,battleEne
s={player,token,powers:Object.create(null),turn:Object.create(null),freeTurn:new WeakSet(),freeBattle:new WeakSet(),
nextTurn:[],bombs:[],negativeStrength:0,autoCount:0,drawCount:0,returns:[],maulBonus:0,vigor:0,queuedAllyEnergy:0};
states.set(player,s);player.addSkill(RULES);
bindCombatStatusSource(player,token.session,"shared",()=>stateOf(player));
token.session.ownResource(s,()=>{if(states.get(player)===s){states.delete(player);player.removeSkill(RULES);s.nextTurn.length=0;s.returns.length=0;}});
return s;
}