ReSemiclip

Кто сквозь кого проходит — правилом над двумя игроками
v0.1.2kukson777 kukson777

Семиклип позволяет игрокам проходить сквозь друг друга. На сервере это делает модуль ReSemiclip; этот модуль даёт плагину amxts сказать, кто сквозь кого проходит, правилом над двумя игроками, (player, target) => boolean, и держит ReSemiclip в курсе.

Возможности

  • Правило, а не битовые маски. Одна функция говорит, проходит ли один игрок сквозь другого; модуль рассчитывает каждую пару и сообщает ReSemiclip.
  • Держится в курсе сам. Появление, смерть, смена команды, вход и уход игрока и изменение любого поля, которое плагины добавили в Player, заново рассчитывают пары — только пары того игрока, с которым это случилось.
  • Об отсутствии модуля — один раз. Без ReSemiclip на сервере ничего не задаётся, а консоль один раз говорит почему.
  • Один экземпляр на сервер. Все плагины, которые им пользуются, задают одно и то же правило.

Установка

Серверу нужен модуль AMX Mod X ReSemiclip (resemiclip_amxx).

npx 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 и остальные) доступны как есть.