🎉 2.0.1.0版本发布
✨ 重构活动BOSS武将包并新增独立PVP武将包 ✨ 完善天书动态难度、过关奖励与羁绊系统 🎨 新增自定义技能选择、羁绊谱册及移动端适配 🔊 整理BOSS配音、图片与模块资源路径 🐛 修复天书关卡、伤害保护及武将包加载问题
@@ -6,7 +6,7 @@ import tianshu from "./sets/tianshu/index.js";
|
||||
// 活动 BOSS 主题清单;新增主题时只需在此接入一次。
|
||||
const bossSets = [
|
||||
["十二生肖", shiershengxiao],
|
||||
["捉鬼驱邪", zhuoguiquxie],
|
||||
["驱鬼逐邪", zhuoguiquxie],
|
||||
["青青子衿", qingqingzijin],
|
||||
["天书乱斗", tianshu],
|
||||
];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -9,7 +9,7 @@ const characterSort = {
|
||||
};
|
||||
|
||||
const characterSortTranslate = {
|
||||
shuYing_pve_zhuoguiquxie: "捉鬼驱邪",
|
||||
shuYing_pve_zhuoguiquxie: "驱鬼逐邪",
|
||||
};
|
||||
|
||||
export { characterSort, characterSortTranslate };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 |