🎉 2.0.1.0版本发布

✨ 重构活动BOSS武将包并新增独立PVP武将包

✨ 完善天书动态难度、过关奖励与羁绊系统

🎨 新增自定义技能选择、羁绊谱册及移动端适配

🔊 整理BOSS配音、图片与模块资源路径

🐛 修复天书关卡、伤害保护及武将包加载问题
This commit is contained in:
2026-08-13 17:25:11 +08:00
parent 49cb75d813
commit b256c0f8e4
54 changed files with 8508 additions and 970 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -6,7 +6,7 @@ import tianshu from "./sets/tianshu/index.js";
// 活动 BOSS 主题清单;新增主题时只需在此接入一次。
const bossSets = [
["十二生肖", shiershengxiao],
["捉鬼驱邪", zhuoguiquxie],
["驱鬼逐邪", zhuoguiquxie],
["青青子衿", qingqingzijin],
["天书乱斗", tianshu],
];
+25
View File
@@ -9,6 +9,7 @@ const characters = {
img: "extension/术樱包/pve/images/青青子衿/caocao_boss_shuying.jpg",
dieAudios: ["ext:术樱包/pve/audio/dead/青青子衿/caocao_boss_shuying.mp3"]
},
simayi_boss_shuying: {
sex: "male",
group: "wei",
@@ -19,6 +20,7 @@ const characters = {
img: "extension/术樱包/pve/images/青青子衿/simayi_boss_shuying.jpg",
dieAudios: ["ext:术樱包/pve/audio/dead/青青子衿/simayi_boss_shuying.mp3"]
},
lvbu_boss_shuying: {
sex: "male",
group: "qun",
@@ -29,6 +31,7 @@ const characters = {
img: "extension/术樱包/pve/images/青青子衿/lvbu_boss_shuying.jpg",
dieAudios: ["ext:术樱包/pve/audio/dead/青青子衿/lvbu_boss_shuying.mp3"]
},
dongzhuo_boss_shuying: {
sex: "male",
group: "qun",
@@ -39,6 +42,28 @@ const characters = {
img: "extension/术樱包/pve/images/青青子衿/dongzhuo_boss_shuying.jpg",
dieAudios: ["ext:术樱包/pve/audio/dead/青青子衿/dongzhuo_boss_shuying.mp3"]
},
yuanshu_boss_shuying: {
sex: "male",
group: "qun",
hp: 4,
skills: ["yongsi_shuying", "wangzun_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/青青子衿/yuanshu_boss_shuying.jpg",
dieAudios: ["ext:术樱包/pve/audio/dead/青青子衿/yuanshu_boss_shuying.mp3"]
},
zhangjiao_boss_shuying: {
sex: "male",
group: "qun",
hp: 4,
skills: ["guidao_shuying", "leiji_shuying", "zhuzheng_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/青青子衿/zhangjiao_boss_shuying.jpg",
dieAudios: ["ext:术樱包/pve/audio/dead/青青子衿/zhangjiao_boss_shuying.mp3"]
},
};
export default characters;
@@ -66,6 +66,28 @@ const dynamicTranslates = {
return `锁定技,回合开始时,你摸X张牌并对至多X名角色造成1点伤害,然后你失去1点体力。X为你已损失体力且最大为${num}。`
},
//袁术
wangzun_shuying(player, skill) {
const num =
getTianshuDifficulty() == "nightmare" ? 2 : 1;
return `锁定技,其他敌方角色的结束阶段,若其本回合:1.没有对你造成伤害,则其弃置${num}张牌;2.对你造成的伤害数超过1点,则你对其造成1点伤害。`;
},
duoxi_shuying(player, skill) {
const num =
getTianshuDifficulty() == "nightmare" ? 2 : 1;
return `其他角色的摸牌阶段,你可以失去1点体力,改为你与其各摸${num}张牌。`;
},
//张角
zhuzheng_shuying(player, skill) {
if (getTianshuDifficulty() == "nightmare") {
return "当一名其他角色使用【杀】指定目标时,若你在其攻击范围内且你不是目标,则你可以将一张手牌置于牌堆顶,取消所有目标,然后你成为目标。";
}
return "其他角色使用【杀】指定除你外的角色时,若你在其攻击范围内,你可以将一张手牌置于牌堆顶,取消所有目标,然后若此【杀】不为黑色,你成为目标。";
},
};
export default dynamicTranslates;
+510
View File
@@ -670,6 +670,516 @@ const skills = {
},
},
//袁术
yongsi_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
forced: true,
locked: true,
group: [
"yongsi_shuying_draw",
"yongsi_shuying_discard",
],
mod: {
maxHandcard(player, num) {
if (_status.currentPhase != player) return;
const damageNum = player
.getHistory("sourceDamage")
.reduce((sum, evt) => sum + (evt.num || 0), 0);
if (damageNum > 1) {
return player.getDamagedHp();
}
},
},
subSkill: {
draw: {
trigger: { player: "phaseDrawBegin2" },
forced: true,
locked: true,
filter(event, player) {
return !event.numFixed;
},
async content(event, trigger, player) {
trigger.num = game.countGroup();
},
},
discard: {
trigger: { player: "phaseDiscardBegin" },
forced: true,
locked: true,
filter(event, player) {
const damageNum = player
.getHistory("sourceDamage")
.reduce((sum, evt) => sum + (evt.num || 0), 0);
return (
damageNum == 0 &&
player.countCards("h") < player.hp
);
},
async content(event, trigger, player) {
await player.drawTo(player.hp);
},
},
},
ai: {
threaten: 1.8,
},
},
wangzun_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
trigger: { global: "phaseJieshuBegin" },
forced: true,
locked: true,
logTarget: "player",
filter(event, player) {
const target = event.player;
if (
!target?.isIn() ||
!player.getEnemies(null, false).includes(target)
) {
return false;
}
const damageNum = player
.getHistory("damage")
.reduce((sum, evt) => {
if (evt.source == target) {
return sum + (evt.num || 0);
}
return sum;
}, 0);
if (damageNum > 1) return true;
return (
damageNum == 0 &&
target.countDiscardableCards(target, "he") > 0
);
},
async content(event, trigger, player) {
const target = trigger.player;
const damageNum = player
.getHistory("damage")
.reduce((sum, evt) => {
if (evt.source == target) {
return sum + (evt.num || 0);
}
return sum;
}, 0);
player.line(target);
if (damageNum == 0) {
const discardNum =
getTianshuDifficulty() == "nightmare" ? 2 : 1;
const num = Math.min(
discardNum,
target.countDiscardableCards(target, "he")
);
if (num > 0) {
await target.chooseToDiscard(num, "he", true);
}
} else if (damageNum > 1 && target.isIn()) {
await target.damage(1, player);
}
},
ai: {
threaten: 1.6,
},
},
duoxi_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
trigger: { global: "phaseDrawBegin1" },
filter(event, player) {
return (
getTianshuDifficulty() != "normal" &&
!event.numFixed &&
event.player?.isIn() &&
event.player != player
);
},
async cost(event, trigger, player) {
const num =
getTianshuDifficulty() == "nightmare" ? 2 : 1;
event.result = await player
.chooseBool(
get.prompt(event.skill, trigger.player),
`失去1点体力,将${get.translation(trigger.player)}的摸牌阶段改为你与其各摸${get.cnNumber(num)}张牌`
)
.set("ai", () => {
const player = get.player();
const trigger = get.event().getTrigger();
const target = trigger.player;
const num =
getTianshuDifficulty() == "nightmare"
? 2
: 1;
if (player.hp <= 1) return false;
const isEnemy = player
.getEnemies(null, false)
.includes(target);
// 避免额外增加敌方摸牌,或削减友方原本的摸牌数
if (isEnemy && trigger.num < num) return false;
if (!isEnemy && trigger.num > num) return false;
return player.hp > 2;
})
.forResult();
},
async content(event, trigger, player) {
const target = trigger.player;
const num =
getTianshuDifficulty() == "nightmare" ? 2 : 1;
player.line(target);
trigger.changeToZero();
await player.loseHp();
const targets = [player, target].filter(
current => current.isIn()
);
if (targets.length) {
await game.asyncDraw(targets, num);
}
},
ai: {
threaten: 1.3,
},
},
//张角
guidao_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
trigger: { global: "judge" },
filter(event, player) {
return player.countCards("hes", {
color: "black",
}) > 0;
},
async cost(event, trigger, player) {
event.result = await player
.chooseCard({
prompt:
`${get.translation(trigger.player)}的` +
`${trigger.judgestr || ""}判定为` +
`${get.translation(trigger.player.judging[0])},` +
`${get.prompt(event.skill)}`,
position: "hes",
filterCard(card, player) {
if (get.color(card, player) != "black") {
return false;
}
const enabled = game.checkMod(
card,
player,
"unchanged",
"cardEnabled2",
player
);
if (enabled != "unchanged") {
return !!enabled;
}
const respondable = game.checkMod(
card,
player,
"unchanged",
"cardRespondable",
player
);
if (respondable != "unchanged") {
return !!respondable;
}
return true;
},
ai(card) {
const trigger = get.event().getTrigger();
const player = get.player();
const judging = get.event().judging;
const result =
trigger.judge(card) -
trigger.judge(judging);
const attitude = get.attitude(
player,
trigger.player
);
if (attitude == 0 || result == 0) {
return 0;
}
let value = get.value(card);
if (get.subtype(card) == "equip2") {
value /= 2;
} else {
value /= 6;
}
return attitude > 0
? result - value
: -result - value;
},
})
.set("judging", trigger.player.judging[0])
.forResult();
},
popup: false,
async content(event, trigger, player) {
const next = player.respond({
cards: event.cards,
skill: event.name,
highlight: true,
noOrdering: true,
});
await next;
const cards = next.cards;
if (!cards?.length) return;
const judgingCard = trigger.player.judging[0];
player.$gain2(judgingCard);
await player.gain(judgingCard);
trigger.player.judging[0] = cards[0];
trigger.orderingCards.addArray(cards);
game.log(trigger.player, "的判定牌改为", cards);
await game.delay(2);
},
ai: {
rejudge: true,
tag: {
rejudge: 1,
},
},
},
leiji_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
trigger: { player: ["useCard", "respond"] },
filter(event, player) {
return (
event.card.name == "shan" &&
player
.getEnemies(null, false)
.some(target => target.isIn())
);
},
line: "thunder",
async cost(event, trigger, player) {
event.result = await player
.chooseTarget(
get.prompt2(event.skill),
(card, player, target) => {
return (
target != player &&
player
.getEnemies(null, false)
.includes(target)
);
}
)
.set("ai", target => {
const player = get.player();
if (target.hasSkill("hongyan")) return 0;
return get.damageEffect(
target,
player,
player,
"thunder"
);
})
.forResult();
},
async content(event, trigger, player) {
const target = event.targets[0];
const judge = target.judge(card => {
const suit = get.suit(card);
if (suit == "spade") return -4;
if (suit == "club") return -2;
return 0;
});
judge.judge2 = result => result.bool == false;
const result = await judge.forResult();
if (result.suit == "spade") {
await target.damage(2, "thunder", player);
} else if (result.suit == "club") {
if (player.isDamaged()) {
await player.recover();
}
if (target.isIn()) {
await target.damage(1, "thunder", player);
}
}
},
ai: {
useShan: true,
threaten: 1.8,
},
},
zhuzheng_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
trigger: { global: "useCard2" },
filter(event, player) {
const source = event.player;
if (
source == player ||
event.card.name != "sha" ||
!event.targets?.length ||
event.targets.includes(player) ||
!source.inRange(player) ||
player.countCards("h") == 0 ||
!player.getEnemies(null, false).includes(source)
) {
return false;
}
const enemies = player.getEnemies(null, false);
return event.targets.some(target => {
return target.isIn() && !enemies.includes(target);
});
},
async cost(event, trigger, player) {
event.result = await player
.chooseCard(
"h",
get.prompt(event.skill, trigger.player),
"将一张手牌置于牌堆顶,取消此【杀】的所有目标"
)
.set("ai", card => {
const player = get.player();
const trigger = get.event().getTrigger();
const enemies = player.getEnemies(null, false);
const protectValue = trigger.targets
.filter(target => !enemies.includes(target))
.reduce((sum, target) => {
return (
sum -
get.effect(
target,
trigger.card,
trigger.player,
player
)
);
}, 0);
const becomeTarget =
getTianshuDifficulty() == "nightmare" ||
get.color(trigger.card) != "black";
const selfValue = becomeTarget
? get.effect(
player,
trigger.card,
trigger.player,
player
)
: 0;
if (protectValue + selfValue <= 0) {
return 0;
}
return 7 - get.value(card);
})
.forResult();
},
async content(event, trigger, player) {
await player.lose(event.cards, ui.cardPile, "insert");
trigger.targets.length = 0;
const becomeTarget =
getTianshuDifficulty() == "nightmare" ||
get.color(trigger.card) != "black";
if (becomeTarget && player.isIn()) {
trigger.all_excluded = false;
trigger.targets.add(player);
game.log(player, "成为了", trigger.card, "的目标");
} else {
trigger.all_excluded = true;
game.log(trigger.card, "失去了所有目标");
}
},
ai: {
threaten: 1.5,
},
},
yinlei_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/青青子衿:1",
trigger: {
player: "loseAfter",
global: [
"equipAfter",
"addJudgeAfter",
"gainAfter",
"loseAsyncAfter",
"addToExpansionAfter",
],
},
forced: true,
locked: true,
filter(event, player) {
if (
getTianshuDifficulty() == "normal" ||
_status.currentPhase == player
) {
return false;
}
const loseEvent = event.getl?.(player);
return (
loseEvent?.cards2?.length > 0 &&
game.hasPlayer(target => {
return target.isIn() && !target.isLinked();
})
);
},
logTarget(event, player) {
return game
.filterPlayer(target => {
return target.isIn() && !target.isLinked();
})
.randomGet();
},
async content(event, trigger, player) {
const targets = game.filterPlayer(target => {
return target.isIn() && !target.isLinked();
});
if (!targets.length) return;
const target = targets.randomGet();
if (target != player) {
player.line(target);
}
await target.link(true);
},
ai: {
threaten: 1.3,
},
},
};
+16
View File
@@ -35,7 +35,23 @@ const translates = {
qubu_shuying: "驭布",
qubu_shuying_info: "锁定技,当友方角色使用【杀】指定目标时,进行一次判定:若结果为黑桃,你对此【杀】的所有目标造成1点伤害。",
yuanshu_boss_shuying: "袁术",
yongsi_shuying: "庸肆",
yongsi_shuying_info: "锁定技,摸牌阶段,你改为摸X张牌(X为存活势力数);弃牌阶段,若你本回合:1.没有造成伤害,将手牌摸至当前体力值;2.造成伤害数超过1点,本回合手牌上限改为已损失体力值。",
wangzun_shuying: "妄尊",
wangzun_shuying_info: "锁定技,其他角色其他敌方角色的结束阶段,若其本回合:1.没有对你造成伤害,则其弃置1张牌;2.对你造成伤害数超过1点,则你对其造成1点伤害。",
duoxi_shuying: "夺玺",
duoxi_shuying_info: "其他角色的摸牌阶段,你可以失去1点体力改为你与其各摸一张牌。",
zhangjiao_boss_shuying: "张角",
guidao_shuying: "鬼道",
guidao_shuying_info: "当一名角色的判定牌生效前,你可以打出一张黑色牌替换之。",
leiji_shuying: "雷击",
leiji_shuying_info: "每当你使用或打出【闪】时,你可以令一名其他角色进行判定,若结果为:黑桃,你对该角色造成2点雷电伤害;梅花,你回复1点体力,然后对该角色造成1点雷电伤害。",
zhuzheng_shuying: "谏征",
zhuzheng_shuying_info: "其他角色使用【杀】指定除你外的角色时,若你在其攻击范围内,你可以将一张手牌置于牌堆顶,取消所有目标,然后若此【杀】不为黑色,你成为目标。",
yinlei_shuying: "引雷",
yinlei_shuying_info: "锁定技,当你失去牌时,随机横置一名角色。",
};
export default translates;
+20 -4
View File
@@ -9,27 +9,41 @@ const characters = {
isBossAllowed: true,
img: "extension/术樱包/pve/images/天书乱斗/shuishengonggong_boss_shuying.png"
},
// huoshenzhurong_boss_shuying: {},
huoshenzhurong_boss_shuying:
{
sex: "male",
group: "shen",
hp: 4,
skills: ["xingxia_shuying", "baoyan_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/天书乱斗/huoshenzhurong_boss_shuying.png"
},
baiqi_boss_shuying:
{
sex: "male",
group: "shen",
hp: 4,
skills: ["changsheng_shuying", "shashen_shuying", "wuan_shuying"],
skills: ["wuan_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/天书乱斗/baiqi_boss_shuying.png"
},
kuafu_boss_shuying:
{
sex: "male",
group: "shen",
hp: 4,
skills: ["shenqu_shuying", "lieben_shuying", "yinjiang_shuying", "zhuri_shuying"],
skills: ["zhuri_shuying", "yinjiang_shuying", "lieben_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/天书乱斗/kuafu_boss_shuying.png"
img: "extension/术樱包/pve/images/天书乱斗/kuafu_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/天书乱斗/kuafu_boss_shuying.mp3"]
},
shaohao_boss_shuying:
{
sex: "male",
@@ -40,6 +54,7 @@ const characters = {
isBossAllowed: true,
img: "extension/术樱包/pve/images/天书乱斗/shaohao_boss_shuying.png"
},
xuannv_boss_shuying: {
sex: "female",
group: "shen",
@@ -50,6 +65,7 @@ const characters = {
img: "extension/术樱包/pve/images/天书乱斗/xuannv_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/天书乱斗/xuannv_boss_shuying.mp3"]
},
hanba_boss_shuying: {
sex: "female",
group: "shen",
+60
View File
@@ -14,6 +14,29 @@ const dynamicTranslates = {
return `锁定技,结束阶段,若本回合进入弃牌堆的卡牌数量:大于4,你回复${hp}点体力;大于5,你摸${card}张牌;大于9,你对所有敌方角色造成${damage}点伤害。`
},
//火神祝融
xingxia_shuying(player, skill) {
const difficulty = getTianshuDifficulty();
let discardNum = 1;
let damageNum = 1;
if (difficulty == "hard") {
discardNum = 2;
} else if (difficulty == "nightmare") {
discardNum = 3;
damageNum = 2;
}
return `锁定技,出牌阶段开始时,你对随机一名友方角色造成1点火焰伤害,然后令所有敌方角色选择一项:1.弃置${discardNum}张红色牌;2.受到你造成的${damageNum}点火焰伤害。`;
},
baoyan_shuying(player, skill) {
if (getTianshuDifficulty() == "nightmare") {
return "锁定技,每当有角色造成火焰伤害后,你获得1个“炎”标记。你的回合结束时,弃置所有“炎”标记,随机对一名敌方角色造成X点火焰伤害。(X为弃置的“炎”标记数)";
}
return "锁定技,每当有角色造成火焰伤害后,你获得1个“炎”标记。你的回合结束时,弃置所有“炎”标记,随机对X名敌方角色各造成1点火焰伤害。(X为弃置的“炎”标记数)";
},
//少昊
baiyi_shuying(player, skill) {
let num = 1;
@@ -27,6 +50,43 @@ const dynamicTranslates = {
return `锁定技,每名敌方角色的回合开始时,若当前轮数小于3,你随机获得其${num}张牌;若当前轮数小于5,对其造成${num}点雷电伤害;若当前轮数小于7,其随机弃置${num}张牌。`;
},
//白起
wuan_shuying(player, skill) {
const difficulty = getTianshuDifficulty();
let num = 1;
if (difficulty == "hard") {
num = 2;
} else if (difficulty == "nightmare") {
num = 3;
}
return `锁定技,你可使用的【杀】的次数+${num},【杀】造成的伤害+1。`;
},
shashen_shuying(player, skill) {
if (getTianshuDifficulty() == "nightmare") {
return "你可以将手牌中的任意牌当【杀】使用或打出。你使用的【杀】造成伤害后,摸3张牌。";
}
return "你可以将手牌中的任意牌当【杀】使用或打出。每回合你使用的第一张【杀】造成伤害后,摸2张牌。";
},
//夸父
yinjiang_shuying(player, skill) {
if (getTianshuDifficulty() == "nightmare") {
return "锁定技,当你在出牌阶段摸牌后,获得牌堆底的牌。若该牌为红色,则对所有敌方角色造成1点伤害。当你在同一阶段内以此法造成过两次或更多的伤害后,该技能失效直到回合结束。";
}
return "锁定技,当你在出牌阶段摸牌后,获得牌堆底的牌。若该牌为红色,则随机对一名敌方角色造成1点伤害。当你在同一阶段内以此法造成过两次或更多的伤害后,该技能失效直到回合结束。";
},
lieben_shuying(player, skill) {
if (getTianshuDifficulty() == "nightmare") {
return "锁定技,当你使用【杀】指定目标后,使用牌堆底的牌进行一次判定:若判定结果为红色,则此【杀】不计入出牌阶段使用次数且伤害+1。";
}
return "锁定技,当你使用【杀】指定目标后,使用牌堆底的牌进行一次判定:若判定结果为红色,则此【杀】不计入出牌阶段使用次数。";
},
//玄女
xuanlie_shuying(player, skill) {
const difficulty = getTianshuDifficulty();
+372 -35
View File
@@ -89,26 +89,229 @@ const skills = {
},
},
//白起
//火神祝融 over
xingxia_shuying: {
mode: ["boss"],
audio: false,
trigger: {
player: "phaseUseBegin",
},
forced: true,
locked: true,
filter(event, player) {
const enemies = player.getEnemies(null, false);
return (
game.hasPlayer(target => {
return target.isIn() && !enemies.includes(target);
}) &&
enemies.some(target => target.isIn())
);
},
async content(event, trigger, player) {
const difficulty = getTianshuDifficulty();
const enemies = player
.getEnemies(null, false)
.filter(target => target.isIn());
const friends = game.filterPlayer(target => {
return target.isIn() && !enemies.includes(target);
});
if (!friends.length || !enemies.length) return;
const friend = friends.randomGet();
player.line(friend, "fire");
await friend.damage(1, player, "fire");
let discardNum = 1;
let damageNum = 1;
if (difficulty == "hard") {
discardNum = 2;
} else if (difficulty == "nightmare") {
discardNum = 3;
damageNum = 2;
}
for (const target of enemies) {
if (!target.isIn()) continue;
const canDiscard =
target.countCards("he", card => {
return (
get.color(card, target) == "red" &&
lib.filter.cardDiscardable(card, target)
);
}) >= discardNum;
let discarded = false;
if (canDiscard) {
const result = await target
.chooseToDiscard(
"he",
discardNum,
`行夏:弃置${get.cnNumber(discardNum)}张红色牌,或受到${get.cnNumber(damageNum)}点火焰伤害`
)
.set("filterCard", (card, target) => {
return (
get.color(card, target) == "red" &&
lib.filter.cardDiscardable(card, target)
);
})
.set("source", player)
.set("damageNum", damageNum)
.set("ai", card => {
const target = get.player();
const damageNum = get.event().damageNum;
if (target.hp <= damageNum) {
return 12 - get.value(card);
}
return 7 - get.value(card);
})
.forResult();
discarded = result.bool;
}
if (!discarded && target.isIn()) {
player.line(target, "fire");
await target.damage(damageNum, player, "fire");
}
}
},
ai: {
threaten: 1.8,
},
},
baoyan_shuying: {
mode: ["boss"],
audio: false,
trigger: {
global: "damageSource",
},
forced: true,
locked: true,
filter(event, player) {
return event.num > 0 && event.hasNature("fire");
},
async content(event, trigger, player) {
player.addMark("baoyan_shuying", 1, false);
},
marktext: "炎",
intro: {
name: "炎",
content: "mark",
},
group: "baoyan_shuying_burst",
subSkill: {
burst: {
audio: false,
trigger: {
player: "phaseEnd",
},
forced: true,
locked: true,
filter(event, player) {
return (
player.countMark("baoyan_shuying") > 0 &&
player
.getEnemies(null, false)
.some(target => target.isIn())
);
},
async content(event, trigger, player) {
const num = player.countMark("baoyan_shuying");
player.removeMark("baoyan_shuying", num, false);
const enemies = player
.getEnemies(null, false)
.filter(target => target.isIn());
if (!enemies.length) return;
if (getTianshuDifficulty() == "nightmare") {
const target = enemies.randomGet();
player.line(target, "fire");
await target.damage(num, player, "fire");
return;
}
const targets = enemies.randomGets(
Math.min(num, enemies.length)
);
for (const target of targets) {
if (!target.isIn()) continue;
player.line(target, "fire");
await target.damage(1, player, "fire");
}
},
},
},
ai: {
threaten: 1.7,
},
},
huoshen_shuying: {
mode: ["boss"],
audio: false,
trigger: {
global: "damageSource",
},
forced: true,
locked: true,
filter(event, player) {
return (
getTianshuDifficulty() == "nightmare" &&
event.num > 0 &&
event.hasNature("fire")
);
},
async content(event, trigger, player) {
if (player.isDamaged()) {
await player.recover();
await player.draw();
} else {
await player.draw(3);
}
},
ai: {
threaten: 2,
},
},
//白起 over
changsheng_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: false,
forced: true,
locked: true,
mod: {
targetInRange(card, player, target) {
if (card.name == "sha") return true;
const difficulty = getTianshuDifficulty();
if (
difficulty != "hard" &&
card.name == "sha"
) {
return true;
}
},
},
ai: {
unequip: true,
threaten: 1.2,
},
},
shashen_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: false,
enable: ["chooseToUse", "chooseToRespond"],
filterCard: true,
position: "h",
viewAs: { name: "sha" },
viewAsFilter(player) {
return player.countCards("h") > 0;
return (
getTianshuDifficulty() != "normal" &&
player.countCards("h") > 0
);
},
prompt: "将一张手牌当【杀】使用或打出",
check(card) {
@@ -118,29 +321,77 @@ const skills = {
subSkill: {
draw: {
trigger: { source: "damageEnd" },
forced: true,
locked: true,
usable(skill, player) {
return getTianshuDifficulty() == "hard"
? 1
: Infinity;
},
filter(event, player) {
return event.card?.name == "sha";
const difficulty = getTianshuDifficulty();
if (
difficulty == "normal" ||
event.card?.name != "sha"
) {
return false;
}
if (difficulty == "nightmare") {
return true;
}
// 困难难度只检查本回合使用的第一张【杀】
const useEvent = event.getParent("useCard");
if (!useEvent) return false;
const firstSha = player.getHistory(
"useCard",
evt => evt.card.name == "sha"
)[0];
return useEvent == firstSha;
},
async content(event, trigger, player) {
await player.draw(3);
const num =
getTianshuDifficulty() == "nightmare"
? 3
: 2;
await player.draw(num);
},
},
},
ai: {
respondSha: true,
skillTagFilter(player) {
return player.countCards("h") > 0;
return (
getTianshuDifficulty() != "normal" &&
player.countCards("h") > 0
);
},
order(item, player) {
return get.order({ name: "sha" }, player) - 0.1;
},
order: 4,
},
},
wuan_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: false,
forced: true,
locked: true,
mod: {
cardUsable(card, player, num) {
if (card.name == "sha") return num + 3;
if (card.name != "sha") return;
const difficulty = getTianshuDifficulty();
if (difficulty == "nightmare") {
return num + 3;
}
if (difficulty == "hard") {
return num + 2;
}
return num + 1;
},
},
trigger: { source: "damageBegin1" },
@@ -150,62 +401,129 @@ const skills = {
async content(event, trigger, player) {
trigger.num++;
},
ai: {
damageBonus: true,
threaten: 2,
},
},
//盘古
//夸父 over
shenqu_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: false,
trigger: { player: "damageEnd" },
forced: true,
locked: true,
filter(event, player) {
return player.countCards("h", card => get.color(card) == "red") > 0;
return (
getTianshuDifficulty() == "nightmare" &&
player.countCards("h", card => get.color(card) == "red") > 0
);
},
async content(event, trigger, player) {
const cards = player.getCards("h", card => get.color(card) == "red");
await player.lose(cards, ui.cardPile, "insert");
await player.lose(cards, ui.cardPile);
await player.draw(cards.length);
},
ai: {
threaten: 1.5,
},
},
lieben_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: "ext:术樱包/pve/audio/skill/天书乱斗:1",
trigger: { player: "useCardToPlayered" },
forced: true,
locked: true,
filter(event, player) {
return event.card.name == "sha" && ui.cardPile.lastChild;
return (
event.card.name == "sha" &&
event.isFirstTarget &&
ui.cardPile.lastChild
);
},
async content(event, trigger, player) {
const judge = player.judge(card => get.color(card) == "red" ? 2 : -1);
const judge = player.judge(card => {
return get.color(card) == "red" ? 2 : -1;
});
judge.directresult = ui.cardPile.lastChild;
judge.judge2 = result => result.bool;
const result = await judge.forResult();
if (result.bool) {
trigger.getParent().addCount = false;
trigger.getParent().baseDamage++;
if (!result.bool) return;
const useEvent = trigger.getParent();
if (useEvent.addCount !== false) {
useEvent.addCount = false;
const stat = player.getStat().card;
if (typeof stat.sha == "number") {
stat.sha--;
}
}
if (getTianshuDifficulty() == "nightmare") {
useEvent.baseDamage = (useEvent.baseDamage || 1) + 1;
}
},
ai: {
threaten: 1.4,
},
},
yinjiang_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: "ext:术樱包/pve/audio/skill/天书乱斗:1",
trigger: { player: "drawEnd" },
forced: true,
locked: true,
filter(event, player) {
return player.isPhaseUsing() && !player.hasSkill("yinjiang_shuying_disabled") && ui.cardPile.lastChild;
return (
player.isPhaseUsing() &&
!player.hasSkill("yinjiang_shuying_disabled") &&
ui.cardPile.lastChild
);
},
async content(event, trigger, player) {
const card = ui.cardPile.lastChild;
await player.gain(card, "gain2");
if (get.color(card) == "red") {
let count = 0;
for (const target of player.getEnemies(null, false).filter(target => target.isIn())) {
player.line(target);
await target.damage(player);
if (get.color(card) != "red") return;
const enemies = player
.getEnemies(null, false)
.filter(target => target.isIn());
if (!enemies.length) return;
const targets =
getTianshuDifficulty() == "nightmare"
? enemies
: [enemies.randomGet()];
let count = 0;
for (const target of targets) {
if (!target?.isIn()) continue;
player.line(target);
const damageEvent = target.damage(1, player);
await damageEvent;
// 只统计实际成立的伤害事件
if (player.getHistory("sourceDamage").includes(damageEvent)) {
count++;
}
player.storage.yinjiang_shuying_count = (player.storage.yinjiang_shuying_count || 0) + count;
if (player.storage.yinjiang_shuying_count >= 2) player.addTempSkill("yinjiang_shuying_disabled", { player: "phaseUseEnd" });
}
if (!count) return;
player.storage.yinjiang_shuying_count =
(player.storage.yinjiang_shuying_count || 0) + count;
if (player.storage.yinjiang_shuying_count >= 2) {
player.addTempSkill("yinjiang_shuying_disabled", {
player: "phaseAfter",
});
}
},
group: "yinjiang_shuying_clear",
@@ -213,22 +531,30 @@ const skills = {
clear: {
trigger: { player: "phaseUseEnd" },
silent: true,
charlotte: true,
async content(event, trigger, player) {
delete player.storage.yinjiang_shuying_count;
},
},
disabled: { charlotte: true },
disabled: {
charlotte: true,
},
},
ai: {
threaten: 2,
},
},
zhuri_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill:1",
audio: "ext:术樱包/pve/audio/skill/天书乱斗:1",
forced: true,
locked: true,
group: ["zhuri_shuying_draw", "zhuri_shuying_bottom"],
subSkill: {
draw: {
trigger: { player: "useCard" },
forced: true,
locked: true,
filter(event, player) {
return get.color(event.card) == "red";
},
@@ -239,16 +565,27 @@ const skills = {
bottom: {
trigger: { global: "useCardAfter" },
forced: true,
locked: true,
filter(event, player) {
return event.targets?.includes(player) && (event.card.name == "sha" || get.type(event.card) == "trick") && event.cards?.filterInD("d").length;
return (
event.targets?.includes(player) &&
(event.card.name == "sha" ||
get.type(event.card) == "trick") &&
event.cards?.someInD("d")
);
},
async content(event, trigger, player) {
const cards = trigger.cards.filterInD("d");
if (!cards.length) return;
game.log(cards, "被置于牌堆底");
for (const card of cards) ui.cardPile.appendChild(card);
await game.cardsGotoPile(cards);
},
},
},
ai: {
threaten: 1.8,
},
},
//少昊 over
@@ -482,7 +819,7 @@ const skills = {
},
},
//旱魃
//旱魃 over
xinji_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/天书乱斗:2",
+14 -8
View File
@@ -7,23 +7,31 @@ const translates = {
juehong_shuying: "决洪",
juehong_shuying_info: "锁定技,准备阶段,你令所有敌方角色自己弃置自己的装备区内的所有牌,若其装备区内没有牌,则改为随机弃置2张手牌",
huoshenzhurong_boss_shuying: "火神祝融",
xingxia_shuying: "行夏",
xingxia_shuying_info: "锁定技,出牌阶段开始时,你对随机1名友方角色造成1点火焰伤害,然后令所有敌方角色选择一项:1.弃置1张红色牌;2.受到你造成的1点火焰伤害",
baoyan_shuying: "爆炎",
baoyan_shuying_info: "锁定技,每当有角色造成火焰伤害后,你获得1个”炎‘标记。你的回合结束时,弃置所有“炎”标记,随机对X名敌人各造成1点火焰伤害。(X为弃置的炎标记数量)",
huoshen_shuying: "火神",
huoshen_shuying_info: "锁定技,每当有角色造成火焰伤害后,你回复1点体力并摸1张牌,若你的体力值为满,改为摸3张牌",
baiqi_boss_shuying: "白起",
changsheng_shuying: "常胜",
changsheng_shuying_info: "锁定技,你使用【杀】无距离限制。",
shashen_shuying: "杀神",
shashen_shuying_info: "你可以将手牌中的任意牌当【杀】使用或打出。你使用的【杀】造成伤害后,摸三张牌。",
shashen_shuying_info: "你可以将手牌中的任意牌当【杀】使用或打出。每回合你使用的第一张【杀】造成伤害后,摸2张牌。",
wuan_shuying: "武安",
wuan_shuying_info: "锁定技,你可使用的【杀】的次数+3,【杀】造成的伤害+1。",
wuan_shuying_info: "锁定技,你可使用的【杀】的次数+1,【杀】造成的伤害+1。",
kuafu_boss_shuying: "盘古",
kuafu_boss_shuying: "夸父",
shenqu_shuying: "神躯",
shenqu_shuying_info: "锁定技,当你受到伤害后,将所有红色手牌置于牌堆底,并摸等量的牌。",
lieben_shuying: "烈奔",
lieben_shuying_info: "锁定技,当你使用【杀】指定目标后,使用牌堆底的牌进行一次判定:若判定结果为红色,则此杀不计入出牌阶段使用次数且伤害+1。",
lieben_shuying_info: "锁定技,当你使用【杀】指定目标后,使用牌堆底的牌进行一次判定:若判定结果为红色,则此杀不计入出牌阶段使用次数。",
yinjiang_shuying: "饮江",
yinjiang_shuying_info: "锁定技,当你在出牌阶段摸牌后,获得牌堆底的1张牌。若该牌为红色,则对所有敌方角色造成1点伤害。当你在同一个阶段内以此法造成过两次活更多的伤害后,该技能失效直到回合结束。",
yinjiang_shuying_info: "锁定技,当你在出牌阶段摸牌后,获得牌堆底的牌。若该牌为红色,则随机对一名敌方角色造成1点伤害。当你在同一阶段内以此法造成过两次或更多的伤害后,该技能失效直到回合结束。",
zhuri_shuying: "逐日",
zhuri_shuying_info: "锁定技,你使用红色牌时摸1张牌。当你成为【杀】或普通锦囊牌的目标后,结算完毕后将该牌放置在牌堆底。",
zhuri_shuying_info: "锁定技,你使用红色牌时摸一张牌。当你成为【杀】或普通锦囊牌的目标后,结算完毕后将该牌放置在牌堆底。",
shaohao_boss_shuying: "少昊",
baiyi_shuying: "白仪",
@@ -31,7 +39,6 @@ const translates = {
shenen_shuying: "神恩",
shenen_shuying_info: "锁定技,所有己方角色使用牌锁定技,所有己方角色使用牌没有距离限制。",
xuannv_boss_shuying: "玄女",
xuanlie_shuying: "玄烈",
xuanlie_shuying_info: "锁定技,回合结束时,对所有本回合你获得过其牌的敌方角色依次造成1点伤害。",
@@ -47,7 +54,6 @@ const translates = {
zhiri_shuying_info: "锁定技,当敌方角色使用红色锦囊牌指定目标后,你摸1张牌。",
fenshi_shuying: "焚世",
fenshi_shuying_info: "锁定技,准备阶段,若你的手牌数小于体力值,则将手牌摸至于体力值相等;若你的手牌数大于体力值,则你对敌方角色造成共计X点伤害,点数随机分配(X为手牌数减体力值)。",
};
export default translates;
+10 -1
View File
@@ -1,3 +1,12 @@
const voices = {};
const voices = {
"#zhuri_shuying1": "狂飙八万里,逐日九重天!",
"#yinjiang_shuying1": "大江三千顷,豪饮一息间!",
"#lieben_shuying1": "奔雷袭紫电,驰羽断青锋!",
"#kuafu_boss_shuying:die": "大泽将涸,金乌难触。",
"#dishi_shuying1": "慈航化众生,司南引轩辕。",
"#jiutian_shuying1": "天上九宫十二城,仙云袅袅授长生。",
"#xuanlie_shuying1": "碧霄一鹤引霞至,玄女箜篌九天来。",
"#xuannv_boss_shuying:die": "世间何来两全法,不负仙旅不负卿。",
};
export default voices;
+15 -15
View File
@@ -6,7 +6,7 @@ const characters = {
skills: ["aotang_shuying", "yunju_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/mengpo_boss_shuying.png"
img: "extension/术樱包/pve/images/驱鬼逐邪/mengpo_boss_shuying.png"
},
baowei_boss_shuying:
@@ -17,7 +17,7 @@ const characters = {
skills: ["eli_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/baowei_boss_shuying.png"
img: "extension/术樱包/pve/images/驱鬼逐邪/baowei_boss_shuying.png"
},
niaozui_boss_shuying:
@@ -28,7 +28,7 @@ const characters = {
skills: ["suoxue_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/niaozui_boss_shuying.png"
img: "extension/术樱包/pve/images/驱鬼逐邪/niaozui_boss_shuying.png"
},
heibaiwuchang_boss_shuying:
@@ -39,8 +39,8 @@ const characters = {
skills: ["mizui_shuying", "qiangzheng_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/heibaiwuchang_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/捉鬼驱邪/heibaiwuchang.mp3"]
img: "extension/术樱包/pve/images/驱鬼逐邪/heibaiwuchang_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/驱鬼逐邪/heibaiwuchang.mp3"]
},
niutoumamian_boss_shuying: {
@@ -50,8 +50,8 @@ const characters = {
skills: ["manji_shuying", "shiyv_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/niutoumamian_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/捉鬼驱邪/niutoumamian.mp3"]
img: "extension/术樱包/pve/images/驱鬼逐邪/niutoumamian_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/驱鬼逐邪/niutoumamian.mp3"]
},
yvsai_boss_shuying: {
@@ -61,7 +61,7 @@ const characters = {
skills: ["anchao_shuying", "guixi_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/yvsai_boss_shuying.png"
img: "extension/术樱包/pve/images/驱鬼逐邪/yvsai_boss_shuying.png"
},
huangfeng_boss_shuying: {
@@ -71,7 +71,7 @@ const characters = {
skills: ["mingchong_shuying", "duzhen_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/huangfeng_boss_shuying.png"
img: "extension/术樱包/pve/images/驱鬼逐邪/huangfeng_boss_shuying.png"
},
riyeyoushen_boss_shuying: {
@@ -81,8 +81,8 @@ const characters = {
skills: ["huiyun_shuying", "yezhong_shuying", "zhoucha_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/riyeyoushen_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/捉鬼驱邪/riyeyoushen.mp3"]
img: "extension/术樱包/pve/images/驱鬼逐邪/riyeyoushen_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/驱鬼逐邪/riyeyoushen.mp3"]
},
guiwang_boss_shuying: {
@@ -92,18 +92,18 @@ const characters = {
skills: ["jizhou_shuying", "danshi_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/guiwang_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/捉鬼驱邪/guiwang.mp3"]
img: "extension/术樱包/pve/images/驱鬼逐邪/guiwang_boss_shuying.png",
dieAudios: ["ext:术樱包/pve/audio/dead/驱鬼逐邪/guiwang.mp3"]
},
yanluowang_boss_shuying: {
sex: "male",
group: "qun",
hp: 4,
skills: ["jizhou_shuying", "danshi_shuying"],
skills: ["dianwei_shuying", "xingpan_shuying"],
isHiddenBoss: true,
isBossAllowed: true,
img: "extension/术樱包/pve/images/捉鬼驱邪/yanluowang_boss_shuying.png"
img: "extension/术樱包/pve/images/驱鬼逐邪/yanluowang_boss_shuying.png"
},
};
+1 -1
View File
@@ -11,7 +11,7 @@ import perfectPairs from "./perfectPairs.js";
import voices from "./voices.js";
import { characterSort, characterSortTranslate } from "./sort.js";
// 捉鬼驱邪主题数据片段,由活动 BOSS 根入口统一注册。
// 驱鬼逐邪主题数据片段,由活动 BOSS 根入口统一注册。
export default {
character: characters,
card: cards,
+91 -5
View File
@@ -511,6 +511,7 @@ const skills = {
return player.getEnemies(null, false).some(target => target.isIn());
},
async content(event, trigger, player) {
const difficulty = getTianshuDifficulty();
const enemies = player.getEnemies(null, false).filter(target => target.isIn());
if (difficulty == "nightmare") {
@@ -667,7 +668,7 @@ const skills = {
},
},
},
shiyu_shuying: {
shiyv_shuying: {
mode: ["boss"],
audio: "ext:术樱包/pve/audio/skill/驱鬼逐邪:1",
trigger: {
@@ -1457,22 +1458,107 @@ const skills = {
},
forced: true,
locked: true,
silent: true,
popup: false,
mark: true,
filter(event, player) {
return (
getTianshuDifficulty() != "normal" &&
!player.storage.zhennu_shuying_used &&
event.changedHp < 0 &&
player.hp <= player.maxHp / 2 &&
player.hp - event.changedHp > player.maxHp / 2
event.originalHp > event.originalMaxHp / 2 &&
event.originalHp + event.changedHp <= event.originalMaxHp / 2
);
},
async content(event, trigger, player) {
player.storage.zhennu_shuying_used = true;
player.storage.zhennu_shuying_pending = true;
player.storage.zhennu_shuying_pending_type = trigger.getParent()?.name;
trigger.zhennu_shuying_pending = true;
player.markSkill("zhennu_shuying");
},
group: "zhennu_shuying_takeover",
subSkill: {
takeover: {
charlotte: true,
forced: true,
silent: true,
popup: false,
forceDie: true,
trigger: {
player: [
"changeHpAfter",
"damageAfter",
"loseHpAfter",
"dyingAfter",
],
},
filter(event, player, name) {
if (
!player.storage.zhennu_shuying_pending ||
!player.isIn() ||
player.hp <= 0
) {
return false;
}
await player.draw(4);
player.insertPhase();
if (name == "dyingAfter") return true;
if (name == "changeHpAfter") {
return (
event.zhennu_shuying_pending === true &&
!["damage", "loseHp"].includes(
player.storage.zhennu_shuying_pending_type
)
);
}
return (
(name == "damageAfter" &&
player.storage.zhennu_shuying_pending_type ==
"damage") ||
(name == "loseHpAfter" &&
player.storage.zhennu_shuying_pending_type ==
"loseHp")
);
},
async content(event, trigger, player) {
delete player.storage.zhennu_shuying_pending;
delete player.storage.zhennu_shuying_pending_type;
player.logSkill("zhennu_shuying");
const phase = event.getParent("phase");
const phaseLoop = event.getParent("phaseLoop");
if (phase && phaseLoop) {
player.insertPhase("zhennu_shuying");
phaseLoop.player = player;
let activeChild = event;
let current = event.getParent();
while (current && current != phaseLoop) {
const pendingEvents = [
...(current.next || []),
...(current.after || []),
];
for (const pendingEvent of pendingEvents) {
if (pendingEvent == activeChild) continue;
pendingEvent.finish();
pendingEvent.untrigger(true);
}
current.finish();
current.untrigger(true);
if (current == phase) break;
activeChild = current;
current = current.getParent();
}
}
await player.draw(4);
if (!phase || !phaseLoop) {
player.insertPhase("zhennu_shuying", true);
}
},
},
},
intro: {
content(storage, player) {
+1 -1
View File
@@ -9,7 +9,7 @@ const characterSort = {
};
const characterSortTranslate = {
shuYing_pve_zhuoguiquxie: "捉鬼驱邪",
shuYing_pve_zhuoguiquxie: "驱鬼逐邪",
};
export { characterSort, characterSortTranslate };
+34 -1
View File
@@ -1,3 +1,36 @@
const voices = {};
const voices = {
"#aotang_shuying1": "品汤消愁,情怨断念。",
"#yunju_shuying1": "云雾缭绕,飓风意动。",
"#guimei_shuying1": "鬼魅生惑,迷乱心神。",
"#eli_shuying1": "豹贲之象,先锋之将。",
"#bingyi_shuying1": "疑难杂病,入天则安。",
"#suoxue_shuying1": "鸟穴虽小,亦有探索之地。",
"#guixi_shuying1": "吸灵唤魂,游鱼而走。",
"#anchao_shuying1": "暗潮涌动,感水知行。",
"#duzhen_shuying1": "毒针入骨,百药难医。",
"#mingchong_shuying1": "虫身虽小,威力无限。",
"#xingpan_shuying1": "你的罪过,只能用刑偿还。",
"#dianwei_shuying1": "阎罗立矩,斧钺杀威!",
"#xuanpan_shuying1": "阎罗殿上杀威棒,判惩凶宵降猢狲!",
"#xuanpan_shuying2": "本王要尔三更死,安能留汝到五更!",
"#xixing_shuying1": "勾魂夺命,震骨吸星!",
"#taiping_shuying1": "一见发财,天下太平!",
"#qiangzheng_shuying1": "敲骨吸髓,征财索命!",
"#mizui_shuying1": "凡间人世百般苦,唯有西方最极乐!",
"#heibaiwuchang_boss_shuying:die": "索命鬼,终被捉!",
"#xiaoshou_shuying1": "冥府鬼域,岂容尔等放肆!",
"#manji_shuying1": "阴兵蛮霸,力大欺理!",
"#shiyu_shuying1": "生财自有道,香烛狱中取!",
"#guizhao_shuying1": "凡夫俗子,安识诡域之计!",
"#niutoumamian_boss_shuying:die": "当牛做马数百载,只求为人一朝夕!",
"#zhoucha_shuying1": "红煞蔽日,凶兵择噬!",
"#yezhong_shuying1": "黑煞出冢,百鬼夜行!",
"#huiyun_shuying1": "附骨之厄,追魂夺魄!",
"#duane_shuying1": "幽冥之馈,尔等安敢弃之!",
"#riyeyoushen_boss_shuying:die": "山河倒悬,阴阳相逆。",
"#jizhou_shuying1": "鬼王凝咒,言出法随!",
"#danshi_shuying1": "猛鬼食人,择魂而噬!",
"#guiwang_boss_shuying:die": "阎罗殿里说枉死,忘川桥头叹奈何!",
};
export default voices;
+14 -2
View File
@@ -1,6 +1,18 @@
import bossSets from "./sets.js";
import { mergeBossSection } from "./merge.js";
const voices = mergeBossSection("语音台词", bossSets, "voices");
// 技能语音按实际 ext 音频目录生成台词键;阵亡语音仍使用“#角色ID:die”。
const voices = {};
for (const [setName, set] of bossSets) {
for (const [key, text] of Object.entries(set.voices || {})) {
const voiceKey = key.endsWith(":die")
? key
: `#ext:术樱包/pve/audio/skill/${setName}/${key.replace(/^#/, "")}`;
if (Object.prototype.hasOwnProperty.call(voices, voiceKey)) {
console.warn(`活动BOSS:跳过${setName}中重复的语音台词 ID“${voiceKey}”`);
continue;
}
voices[voiceKey] = text;
}
}
export default voices;

Before

Width:  |  Height:  |  Size: 579 KiB

After

Width:  |  Height:  |  Size: 579 KiB

Before

Width:  |  Height:  |  Size: 590 KiB

After

Width:  |  Height:  |  Size: 590 KiB

Before

Width:  |  Height:  |  Size: 680 KiB

After

Width:  |  Height:  |  Size: 680 KiB

Before

Width:  |  Height:  |  Size: 687 KiB

After

Width:  |  Height:  |  Size: 687 KiB

Before

Width:  |  Height:  |  Size: 503 KiB

After

Width:  |  Height:  |  Size: 503 KiB

Before

Width:  |  Height:  |  Size: 621 KiB

After

Width:  |  Height:  |  Size: 621 KiB

Before

Width:  |  Height:  |  Size: 608 KiB

After

Width:  |  Height:  |  Size: 608 KiB

Before

Width:  |  Height:  |  Size: 598 KiB

After

Width:  |  Height:  |  Size: 598 KiB

Before

Width:  |  Height:  |  Size: 617 KiB

After

Width:  |  Height:  |  Size: 617 KiB

Before

Width:  |  Height:  |  Size: 570 KiB

After

Width:  |  Height:  |  Size: 570 KiB

Before

Width:  |  Height:  |  Size: 717 KiB

After

Width:  |  Height:  |  Size: 717 KiB

Before

Width:  |  Height:  |  Size: 705 KiB

After

Width:  |  Height:  |  Size: 705 KiB

Before

Width:  |  Height:  |  Size: 638 KiB

After

Width:  |  Height:  |  Size: 638 KiB

Before

Width:  |  Height:  |  Size: 654 KiB

After

Width:  |  Height:  |  Size: 654 KiB