Files
noname-shuying/character/skill.js
T
2026-08-11 15:59:31 +08:00

389 lines
15 KiB
JavaScript

import { lib, game, ui, get, ai, _status } from "../../../noname.js";
const skills = {
huashen_shuying: {
audio: "ext:术樱包/character/audio/zuoci:2",
inherit: "rehuashen",
unique: true,
init(player, skill) {
if (!player.storage.rehuashen) {
player.storage.rehuashen = {
character: [],
choosed: [],
map: {},
};
}
player.storage[skill] = player.storage.rehuashen;
},
async content(event, trigger, player) {
const oldCharacter = player.storage.rehuashen?.current;
const oldSkill = player.storage.rehuashen?.current2;
const transitionKey = "jihun_shuying_transition";
// 单独处理重铸,保留本次实际移除的化身牌信息
if (event.cost_data === "制衡其他化身") {
_status.noclearcountdown = true;
const id = lib.status.videoId++;
const prompt = "化身:选择制衡至多两张武将牌";
const cards = player.storage.rehuashen.character;
if (player.isOnline2()) {
player.send(
(cards, prompt, id) => {
const dialog = ui.create.dialog(
prompt,
[cards, lib.skill.rehuashen.$createButton]
);
dialog.videoId = id;
},
cards,
prompt,
id
);
}
const dialog = ui.create.dialog(
prompt,
[cards, lib.skill.rehuashen.$createButton]
);
dialog.videoId = id;
if (!event.isMine()) {
dialog.style.display = "none";
}
const result = await player
.chooseButton(true)
.set("dialog", id)
.set("selectButton", [1, 2])
.set(
"filterButton",
button => button.link !== get.event().current
)
.set("current", player.storage.rehuashen.current)
.forResult();
if (player.isOnline2()) {
player.send("closeDialog", id);
}
dialog.close();
delete _status.noclearcountdown;
if (!_status.noclearcountdown) {
game.stopCountChoose();
}
const removedCharacters = result.links || [];
lib.skill.rehuashen.removeHuashen(
player,
removedCharacters
);
if (
player.storage.jihun_shuying_retainedCharacter &&
removedCharacters.includes(
player.storage.jihun_shuying_retainedCharacter
)
) {
delete player.storage.jihun_shuying_retained;
delete player.storage.jihun_shuying_retainedCharacter;
delete player.storage.jihun_shuying_ignoredEvents;
await player.removeAdditionalSkills(
"jihun_shuying_retained"
);
}
lib.skill.rehuashen.addHuashens(
player,
removedCharacters.length
);
player.storage.huashen_shuying =
player.storage.rehuashen;
player.syncStorage("huashen_shuying");
player.updateMarks("huashen_shuying");
return;
}
// 切换前为当前技能增加临时所有权。官方化身移除旧来源时,
// getRemovableAdditionalSkills 会因此保留技能本体及全部状态。
const protectOldSkill = Boolean(
oldSkill && player.hasSkill("jihun_shuying")
);
if (
protectOldSkill &&
!player.additionalSkills[transitionKey]?.includes(oldSkill)
) {
if (!Array.isArray(player.additionalSkills[transitionKey])) {
player.additionalSkills[transitionKey] = [];
}
player.additionalSkills[transitionKey].push(oldSkill);
game.broadcast(
(player, map) => {
player.additionalSkills = map;
},
player,
player.additionalSkills
);
_status.event.clearStepCache();
}
await lib.skill.rehuashen.content(event, trigger, player);
const storage = player.storage.rehuashen;
const changed = Boolean(
oldSkill &&
(
oldCharacter !== storage?.current ||
oldSkill !== storage?.current2
)
);
if (
changed &&
player.hasSkill("jihun_shuying")
) {
// 过渡来源会阻止官方流程物理移除旧技能,因此这里仅删除
// rehuashen 对旧技能的映射,不触发 removeSkill/onremove。
if (
oldSkill !== storage.current2 &&
player.additionalSkills.rehuashen?.includes(oldSkill)
) {
player.$removeAdditionalSkills("rehuashen", oldSkill);
_status.event.clearStepCache();
}
// 新的当前技能已经登记完毕后,再结束上一次羁魂保留。
if (player.additionalSkills.jihun_shuying_retained) {
await player.removeAdditionalSkills(
"jihun_shuying_retained"
);
}
delete player.storage.jihun_shuying_retained;
delete player.storage.jihun_shuying_retainedCharacter;
delete player.storage.jihun_shuying_ignoredEvents;
player.logSkill("jihun_shuying");
if (oldSkill && oldSkill !== storage.current2) {
const ignoredEvents = player
.getAllHistory("useSkill", history => {
return get.sourceSkillFor(history) === oldSkill;
})
.map(history => history.event)
.filter(Boolean);
let currentEvent = _status.event;
while (currentEvent) {
const eventSkill = currentEvent.sourceSkill ||
currentEvent.skill ||
(lib.skill[currentEvent.name] ? currentEvent.name : null);
if (
eventSkill &&
get.sourceSkillFor(eventSkill) === oldSkill &&
!ignoredEvents.includes(currentEvent)
) {
ignoredEvents.push(currentEvent);
}
currentEvent = currentEvent.parent;
}
player.storage.jihun_shuying_retained = oldSkill;
player.storage.jihun_shuying_retainedCharacter =
oldCharacter;
player.storage.jihun_shuying_ignoredEvents = ignoredEvents;
// 此时 oldSkill 仍由过渡键持有,增加羁魂来源不会重新
// 初始化技能,也不会影响牌、标记和 storage。
const retainedKey = "jihun_shuying_retained";
if (!Array.isArray(player.additionalSkills[retainedKey])) {
player.additionalSkills[retainedKey] = [];
}
if (!player.additionalSkills[retainedKey].includes(oldSkill)) {
player.additionalSkills[retainedKey].push(oldSkill);
}
game.broadcast(
(player, map) => {
player.additionalSkills = map;
},
player,
player.additionalSkills
);
_status.event.clearStepCache();
}
}
// 最终所有权建立完毕后再撤销过渡来源。
if (player.additionalSkills[transitionKey]) {
await player.removeAdditionalSkills(transitionKey);
}
player.storage.huashen_shuying = storage;
player.syncStorage("huashen_shuying");
player.updateMarks("huashen_shuying");
},
onremove(player) {
player.removeAdditionalSkill("rehuashen");
player.removeAdditionalSkill("jihun_shuying_retained");
player.removeAdditionalSkill("jihun_shuying_transition");
delete player.storage.rehuashen;
delete player.storage.huashen_shuying;
delete player.storage.jihun_shuying_retained;
delete player.storage.jihun_shuying_retainedCharacter;
delete player.storage.jihun_shuying_ignoredEvents;
},
ai: {
threaten: 2,
},
},
xinsheng_shuying: {
audio: "ext:术樱包/character/audio/zuoci:2",
unique: true,
trigger: {
player: "damageEnd",
},
filter(event, player) {
return event.num > 0 &&
player.hasSkill("huashen_shuying") &&
player.storage.rehuashen;
},
async cost(event, trigger, player) {
const controls = ["获得一张新化身"];
if (player.storage.rehuashen.character?.length) {
controls.push("更换所展示的化身");
}
controls.push("cancel2");
const result = await player
.chooseControl(controls)
.set("prompt", get.prompt(event.skill))
.set("prompt2", "获得一张新化身牌,或更换所展示的化身牌")
.set("ai", () => {
const player = get.player();
const controls = get.event().controls;
if (!controls.includes("更换所展示的化身")) {
return "获得一张新化身";
}
const storage = player.storage.rehuashen;
const currentRank = storage.current2 ?
get.skillRank(storage.current2, "in") : 0;
const skills = storage.character
.flatMap(name => storage.map[name] || [])
.unique();
const bestRank = skills.reduce((max, skill) => {
return Math.max(max, get.skillRank(skill, "in"));
}, 0);
if (bestRank > currentRank + 1) {
return "更换所展示的化身";
}
return "获得一张新化身";
})
.forResult();
event.result = {
bool: result.control !== "cancel2",
cost_data: result.control,
};
},
async content(event, trigger, player) {
if (event.cost_data === "获得一张新化身") {
lib.skill.rehuashen.addHuashens(player, 1);
player.storage.huashen_shuying = player.storage.rehuashen;
player.syncStorage("huashen_shuying");
player.updateMarks("huashen_shuying");
return;
}
const next = game.createEvent("huashen_shuying_change");
next.player = player;
next.skill = "huashen_shuying";
next.cost_data = "替换当前化身";
next.setContent(lib.skill.huashen_shuying.content);
await next;
},
ai: {
combo: "huashen_shuying",
maixie: true,
maixie_hp: true,
effect: {
target(card, player, target) {
if (
get.tag(card, "damage") &&
target.hasSkill("huashen_shuying")
) {
return [1, 0.7];
}
},
},
},
},
jihun_shuying: {
audio: "ext:术樱包/character/audio/zuoci:2",
locked: true,
group: "jihun_shuying_clear",
onremove(player) {
player.removeAdditionalSkill("jihun_shuying_retained");
player.removeAdditionalSkill("jihun_shuying_transition");
delete player.storage.jihun_shuying_retained;
delete player.storage.jihun_shuying_retainedCharacter;
delete player.storage.jihun_shuying_ignoredEvents;
},
ai: {
combo: "huashen_shuying",
},
subSkill: {
clear: {
charlotte: true,
silent: true,
lastDo: true,
priority: -Infinity,
trigger: {
player: [
"useSkillAfter",
"useCardAfter",
"respondAfter",
"triggerAfter",
"skillAfter",
],
},
hookTrigger: {
after(event, player) {
const retained =
player.storage.jihun_shuying_retained;
return Boolean(
retained &&
event.skill &&
get.sourceSkillFor(event.skill) === retained
);
},
},
filter(event, player) {
const retained =
player.storage.jihun_shuying_retained;
if (
!retained ||
!event.skill ||
get.sourceSkillFor(event.skill) !== retained
) {
return false;
}
const ignoredEvents =
player.storage.jihun_shuying_ignoredEvents || [];
return !ignoredEvents.includes(event);
},
async content(event, trigger, player) {
delete player.storage.jihun_shuying_retained;
delete player.storage.jihun_shuying_retainedCharacter;
delete player.storage.jihun_shuying_ignoredEvents;
await player.removeAdditionalSkills(
"jihun_shuying_retained"
);
},
},
},
},
};
export default skills;