@bot-shiki/koishi-plugin-werewolf
Version:
Touhou werewolf game
109 lines (108 loc) • 4.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const koishi_1 = require("koishi");
const _1 = require(".");
const utils_1 = require("../utils");
class DeathAction extends _1.Action {
async action(speakers = []) {
this.game.check();
const dying = this.game.seats.filter(c => !c.isDead && c.killer);
if (!dying.length)
return this.lastWords(speakers);
dying.forEach((char) => {
char.scapegoat = null;
});
const revengers = new Map();
const others = this.game.room.filter((p) => {
const char = this.game.chars.get(p);
return !char || char.isDead;
});
const tasks = [others.broadcast(this.game.weather === 'souten' ? (0, utils_1.t)('death.souten') : (0, utils_1.t)('death.confirm'))];
tasks.push(...this.game.seats.filter(c => !c.isDead).map(async (char) => {
if (char.killer) {
if (char.killer !== 'yukari' && char.isRevenger) {
await char.player.send((0, utils_1.t)('death.revenge-hint'));
const target = await char.select((c) => ({
disabled: !!c.killer,
}), 60000, true);
if (target)
revengers.set(char, target);
}
else {
await char.player.pause(60000, null, true);
}
}
else {
if (this.game.weather !== 'souten') {
await char.player.pause(60000, null, true);
}
else {
await char.player.send((0, utils_1.t)('death.souten-hint'));
const result = await char.select((c) => ({
disabled: !c.killer || c.isOut,
}), 60000, true);
const target = this.game.seats[+result - 1];
if (!target)
return;
if (!target.scapegoat || this.getDistance(target, char) < this.getDistance(target, target.scapegoat)) {
target.scapegoat = char;
}
}
}
}));
await Promise.all(tasks);
const output = dying.map((char) => {
if (char.scapegoat) {
revengers.delete(char);
char.scapegoat.killer = char.killer;
char.scapegoat.isOut = true;
speakers.push(char.scapegoat);
char.killer = null;
return (0, utils_1.t)('death.souten-result-1', [char.player.name, char.scapegoat.player.name]);
}
else if (revengers.has(char)) {
char.isOut = true;
char.isWellKnown = true;
speakers.push(char);
revengers.get(char).killer = char.identity;
return (0, utils_1.t)('death.revenge', [char.player.name, (0, utils_1.t)(`character.${char.identity}.name`)]);
}
else if (this.game.weather === 'souten') {
char.isOut = true;
speakers.push(char);
return (0, utils_1.t)('death.souten-result-0', [char.player.name]);
}
else {
char.isOut = true;
speakers.push(char);
}
}).filter(Boolean);
await this.game.room.broadcast(output.map(el => (0, koishi_1.h)('p', el)));
return this.action(speakers);
}
getDistance(char1, char2) {
const chars = this.game.seats.filter(c => !c.isDead);
const index1 = chars.indexOf(char1);
const index2 = chars.indexOf(char2);
const dist = Math.abs(index1 - index2);
return Math.min(dist, chars.length - dist);
}
async lastWords(speakers) {
if (this.game.dayCount > 2 || !speakers.length)
return;
const others = this.game.room.filter(p => !speakers.includes(this.game.chars.get(p)));
speakers.forEach(c => c.player.allowSpeech = true);
await Promise.all([
others.broadcast((0, utils_1.t)('death.last-words')),
...speakers.map(async (char) => {
await char.player.send((0, utils_1.t)('death.last-words-hint'));
await char.player.select(['.', '。'], 60000);
}),
]);
speakers.forEach(c => c.player.allowSpeech = false);
if (speakers.some(c => c.isSage)) {
await this.game.sage.transfer();
}
}
}
exports.default = DeathAction;