🎉 2.0.1.0版本发布

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

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

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

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

🐛 修复天书关卡、伤害保护及武将包加载问题
This commit is contained in:
2026-08-13 17:28:42 +08:00
parent 49cb75d813
commit 02e7a642ea
54 changed files with 8509 additions and 952 deletions
+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;