Семиклип позволяет игрокам проходить сквозь друг друга. На сервере это делает модуль ReSemiclip; этот модуль даёт плагину amxts сказать, кто сквозь кого проходит, правилом над двумя игроками, (player, target) => boolean, и держит ReSemiclip в курсе.
Возможности
- Правило, а не битовые маски. Одна функция говорит, проходит ли один игрок сквозь другого; модуль рассчитывает каждую пару и сообщает ReSemiclip.
- Держится в курсе сам. Появление, смерть, смена команды, вход и уход игрока и изменение любого поля, которое плагины добавили в
Player, заново рассчитывают пары — только пары того игрока, с которым это случилось. - Об отсутствии модуля — один раз. Без ReSemiclip на сервере ничего не задаётся, а консоль один раз говорит почему.
- Один экземпляр на сервер. Все плагины, которые им пользуются, задают одно и то же правило.
Установка
Серверу нужен модуль AMX Mod X ReSemiclip (resemiclip_amxx).
npx amxts module add resemiclip
pnpm amxts module add resemiclip
yarn amxts module add resemiclip
bunx amxts module add resemiclip
Команда ставит пакет и добавляет его в amxts.config.ts проекта:
export default defineConfig({
modules: ["@amxts/resemiclip"],
});
Использование
Плагин пользуется модулем как semiclip, без строки импорта: сборка добавляет импорт в те плагины, которые им пользуются, и собирает модуль, только когда им пользуется хоть один.
Союзники проходят сквозь друг друга:
semiclip.rule = (player, target) => player.team == target.team;
Больше ничего не нужно: модуль рассчитывает каждую пару и заново рассчитывает пары игрока, когда тот появляется, умирает, меняет команду, входит или уходит. Присваивание rule забирает правила у конфига ReSemiclip; semiclip.rule = null возвращает их, и так же — перезагрузка плагинов, смена карты и остановка плагина, который задал правило (его выгрузили или перезагрузили), пока правило не задано снова.
Правило, которое меняется в игре
spawnProtected ниже — собственное поле плагина в Player, объявленное через declare module: сначала оно false, его читают и пишут все плагины сервера, а когда игрок уходит, оно сбрасывается. Только что появившийся игрок 3 секунды проходит сквозь всех живых, а союзники — сквозь друг друга:
declare module "@amxts/core" {
interface Player {
spawnProtected: boolean;
}
}
semiclip.rule = (player, target) =>
player.isAlive && target.isAlive && (player.spawnProtected || target.spawnProtected || player.team == target.team);
game.addEventListener("spawn", ({ player }) => {
player.spawnProtected = true; // 3 секунды проходит сквозь всех
setTimeout(() => (player.spawnProtected = false), 3000);
});
Модуль сам заново рассчитывает пары, когда поле меняется, — при появлении и когда таймер его снимает, — без вызова update().
Когда пары рассчитываются
| Когда | Какие пары |
|---|---|
задано rule | все пары |
| игрок вошёл в игру | его |
| игрок появился, умер или сменил команду | его |
у игрока изменилось поле, которое плагины добавили в Player, — любым плагином или Pawn | его |
| игрок ушёл | сквозь его слот больше никто не проходит |
semiclip.update(player) | пары player |
semiclip.update() | все пары |
update() — для того, что читает правило, но чего модуль не слышит: режим раунда в переменной, собственная запись плагина об игроке:
let everyone = false;
semiclip.rule = (player, target) => everyone || player.team == target.team;
server.addCommand("/party", () => {
everyone = !everyone;
semiclip.update();
});
В обе стороны
rule(player, target) говорит, проходит ли player сквозь target. ReSemiclip пропускает двух игроков друг сквозь друга, только когда это разрешено в обе стороны, поэтому правило, которое в одну сторону говорит да, а в другую нет, оставляет пару твёрдой. Пару пропускает правило, которое читается одинаково в обе стороны, — player.team == target.team, player.spawnProtected || target.spawnProtected.
Одно правило
Правило на сервере одно. Плагин, который задаёт его поверх правила другого плагина, заменяет его, а консоль предупреждает: действует последнее заданное. Плагины, у каждого из которых есть своё слово, пишут его в поля (player.spawnProtected), которые читает одно правило.
Без ReSemiclip на сервере
Ничего не задаётся: модуль не забирает правила, passesThrough никого не даёт, а консоль один раз говорит, что модуля resemiclip на сервере нет.
API
| Член | Что это |
|---|---|
semiclip.rule | (player, target) => boolean — проходит ли player сквозь target. Присваивание забирает правила и рассчитывает каждую пару; null возвращает их. |
semiclip.update(player?) | Заново рассчитывает пары player или всех, после того как изменилось то, что читает правило и чего модуль не слышит. |
semiclip.passesThrough(player) | Игроки, сквозь которых проходит player, как это сейчас у ReSemiclip. |
Pawn-плагинам собственные нативы ReSemiclip (resemiclip_set_user_mask и остальные) доступны как есть.