Относительные векторы Elite Script
Для чего они нужны
Относительные векторы — это векторы, привязанные к определённому, но динамическому местоположению.
Например, чтобы притянуть игрока к движущемуся боссу, вычислите вектор от позиции игрока к позиции босса. Постоянный вектор не может следовать за изменением их позиций.
Относительные векторы позволяют направлять снаряды, запускать падающие блоки и задавать направление взгляда. В качестве относительных смещений они могут разместить подкрепление за игроком или продлить луч за его цель.
Контекст использования
Относительные векторы используются в контекстах действий с YAML-ключом RelativeVector:. Это включает такие действия, как:
SUMMON_ENTITY- Устанавливает скорость (направление движения и скорость) призванной сущностиSUMMON_REINFORCEMENT- Задаёт скорость появившегося подкрепленияSPAWN_PARTICLE- Задаёт вектор движения внутри отдельной записиparticles:; поле на уровне действия для этого не используетсяPUSH- Устанавливает скорость толчкаSPAWN_FALLING_BLOCK- Устанавливает скорость падающего блокаSET_FACING- Устанавливает направление, куда смотрит сущность
Остальные действия разбирают корректный блок RelativeVector:, но не используют его. Эти ключи не чувствительны к регистру, поэтому записи частиц принимают и RelativeVector:, и relativeVector:. Значения типов целей сохраняют документированное написание в верхнем регистре.
В действиях скорости RelativeVector имеет приоритет над vValue; значения не складываются. PUSH вычисляет один вектор для всех выбранных сущностей и применяет его через один тик. SET_FACING также вычисляет одно направление для всех выбранных сущностей.
Для изменения позиций целей помещайте relativeOffset: внутрь блока цели, например Target, FinalTarget, Target2 или FinalTarget2. На уровне действия relativeOffset: вызывает сообщение Failed to read key relativeOffset .... Он действует, только если у действия нет блока Target, потому что тогда цель по умолчанию SELF читает ключи цели из самого действия. См. раздел относительных смещений ниже.
Как работают векторы?
Если вы не знаете или не помните, что такое векторы и как они работают, можете думать о векторах как о стрелках, указывающих от одной точки к другой.
Таким образом, одним из свойств векторов является их длина. Эта длина важна; в случае стрел это скорость, с которой выстреливается стрела, в случае попытки получить смещённые точки от определённого местоположения — это расстояние от этой точки. Вещи, находящиеся дальше, будут иметь большую длину вектора, а ближние — меньшую.
Для некоторых механик вы, вероятно, не захотите полагаться на то, насколько далеко друг от друга находятся две точки, поскольку вам нужно просто получить направление. К счастью, вы можете использовать нормализацию вектора, которая гарантирует сохранение направления, но изменяет длину до 1.0. Затем вы можете использовать множители для лёгкого изменения вектора, пока не будете удовлетворены смещением, которое он обеспечивает, или скоростью, которую он даёт.
Свойства
| Значение | Подробности | Обязательно? | Значение по умолчанию |
|---|---|---|---|
SourceTarget | Цель в точке, откуда будет начинаться вектор | ✅ | none |
DestinationTarget | Цель в конечной точке вектора | ✅ | none |
normalize | Определяет, должен ли вектор быть нормализован | ❌ | false |
multiplier | Умножает длину вектора. Вы можете рандомизировать это значение, используя ~. Пример: 1.0~2.5. | ❌ | 1.0 |
offset | Добавляет постоянное смещение. Поддерживает случайные диапазоны через ~, например 0~5,0~2,0~10. | ❌ | 0,0,0 |
Рандомизация
И multiplier, и offset поддерживают рандомизацию с помощью разделителя тильда (~):
- Для multiplier: Используйте
min~max, например1.0~2.5. Этот пример выбирает значения от 1.0 до 2.5, не включая 2.5. - Для offset: Используйте формат
x1~x2,y1~y2,z1~z2(например,0~5,0~2,0~10). Каждый компонент (X, Y, Z) рандомизируется независимо.
Значения выбираются при каждом вычислении вектора. Для случайных компонентов смещения действует то же правило: от min до max, не включая max.
Пример
eliteScript:
ShootChicken:
Events:
- EliteMobDamagedByPlayerEvent
Actions:
- action: SUMMON_ENTITY
sValue: CHICKEN
Target:
targetType: SELF
RelativeVector:
SourceTarget:
targetType: SELF
DestinationTarget:
targetType: DIRECT_TARGET
normalize: true
multiplier: 2.0
Запускает курицу от босса к атакующему игроку.
eliteScript:
ShootArrow:
Events:
- EliteMobDamagedByPlayerEvent
Actions:
- action: SUMMON_ENTITY
sValue: ARROW
Target:
targetType: SELF
RelativeVector:
SourceTarget:
targetType: SELF
DestinationTarget:
targetType: DIRECT_TARGET
normalize: true
multiplier: 2.0
Запускает стрелу к атакующему игроку. Для сущностей-снарядов при живом боссе SUMMON_ENTITY использует механизм запуска снарядов босса. Поэтому снаряд выходит из босса, даже если Target действия задаёт другую позицию.
eliteScript:
SpawnReinforcement:
Events:
- EliteMobDamagedByPlayerEvent
Actions:
- action: SUMMON_ENTITY
sValue: ZOMBIE
Target:
targetType: DIRECT_TARGET
relativeOffset:
SourceTarget:
targetType: SELF
DestinationTarget:
targetType: DIRECT_TARGET
normalize: true
multiplier: 2.0
Создаёт обычного зомби на два блока дальше игрока по линии от босса к игроку. Несмотря на имя скрипта, это не подкрепление EliteMobs. relativeOffset находится внутри Target: он меняет позицию появления, а не скорость. Используется полная трёхмерная линия, а не направление взгляда игрока; смещение не ищет землю и не проверяет столкновения.
eliteScript:
Example:
Events:
- EliteMobDamagedByPlayerEvent
Zone:
Shape: SPHERE
target:
targetType: SELF_SPAWN
offset: 0,0,0
track: false
filter: PLAYER
radius: 6
Actions:
- action: SPAWN_PARTICLE
repeatEvery: 38
times: 5
Target:
targetType: ZONE_FULL
track: false
coverage: 0.9
particles:
- particle: FLAME
RelativeVector:
SourceTarget:
targetType: ACTION_TARGET
track: true
DestinationTarget:
targetType: SELF_SPAWN
offset: 0,-0.5,0
speed: 0.05
Создаёт повторяющиеся всплески пламени, движущегося внутрь сферы вокруг точки появления. Сама зона не сжимается.
Как это работает:
- Зона предоставляет геометрические точки внутри сферы радиусом шесть блоков.
filter: PLAYERвлияет на выбор сущностей, а не используемые здесь позиции частиц. coverage: 0.9даёт каждой созданной точке примерно 90 % вероятности выбора.track: falseдействия сохраняет этот выбор для повторов текущего запуска.- Вектор каждой частицы направлен от её точки появления (
ACTION_TARGET) на полблока ниже точки появления босса (SELF_SPAWNсoffset: 0,-0.5,0). - Вектор вычисляется при создании частицы.
ACTION_TARGETнапрямую использует позицию, переданную действием; вложенныйtrackне управляет уже летящими частицами. - Относительный вектор частицы заменяет
x,y,zи принудительно задаётamount: 0для направленного испускания.speedвсё ещё передаётся Bukkit, а тип частицы определяет итоговое движение. - Действие выполняется пять раз через 38 тиков, если запланированная работа не отменена. Каждый подходящий удар начинает новый запуск, поскольку в примере нет перезарядки.
Порядок операций
Порядок применения свойств следующий:
Вычисление вектора -> normalize -> multiplier -> offset
Технические заметки
Нормализация вектора: Для ненулевого вектора сохраняет направление и задаёт длину 1.0 до применения множителя и смещения.
Отрицательные Множители: Множитель может быть отрицательным для разворота направления вектора. Например, множитель -1.0 будет указывать в противоположном направлении.
Координаты Смещения: Смещение применяется в мировых координатах, а не относительно направления вектора. Оно добавляется после всех остальных вычислений.
Валидация Мира: Исходная и конечная цели должны находиться в одном мире. Если они находятся в разных мирах, возвращается нулевой вектор (0, 0, 0), что может привести к сбою действий или неожиданному поведению.
Отсутствующие цели: Пустая разрешённая коллекция источника или назначения возвращает нулевой вектор до применения множителя и смещения. Это относится и к конечной точке DIRECT_TARGET, когда у события нет прямой цели. Отсутствующий блок SourceTarget или DestinationTarget по-прежнему вызывает ошибку.
Если корректные исходная и конечная позиции совпадают, вектор имеет нулевую длину. normalize: true оставляет его нулевым, поэтому остаётся только собственный offset относительного вектора. Если цель даёт несколько позиций, используется первая, без гарантии выбора ближайшей. Используйте одиночную цель вроде DIRECT_TARGET, когда направление должно быть однозначным.
ACTION_TARGET: Использует переданную действием позицию, обходя вложенные настройки цели offset, relativeOffset и track. Для частиц это позиция частицы; для сущностей и падающих блоков — запрошенная позиция появления; для скорости подкрепления — позиция созданного подкрепления. Для PUSH и SET_FACING это позиция босса, а не каждой выбранной сущности. В relativeOffset цели это смещаемая позиция после применения обычного offset этой цели.
Контекст Скорости против Позиции: В контекстах действий, таких как SUMMON_ENTITY, RelativeVector устанавливает скорость (движение) сущности. В контекстах целей relativeOffset устанавливает смещение позиции (корректировку местоположения). Используется одна и та же базовая система, но интерпретация отличается в зависимости от контекста.
Применяйте relativeOffset к целям вроде SELF, SELF_SPAWN, DIRECT_TARGET, LOCATION или LOCATIONS, в том числе задающим начало или конец зоны. Для ZONE_FULL / ZONE_BORDER он смещает каждую выбранную точку зоны. На LANDING_LOCATION и INHERIT_SCRIPT_TARGET он не влияет. См. правила смещений целей.
Относительное смещение Elite Script
Для чего они нужны?
Относительные смещения функционируют аналогично относительным векторам, но их цель — добавить гибкость к смещениям. Они позволяют динамически корректировать позиции при написании скриптов, упрощая точную настройку позиций целей или эффектов в зависимости от контекста.
Как работают относительные смещения?
Относительные смещения аддитивны, то есть то, во что разрешится смещение, будет добавлено к базовому значению (например, к местоположению или вектору).
Разберём пример:
У вас есть зона луча:
Цель 1этоSELF(босс).Target 2—DIRECT_TARGET, игрок, переданный событием.
Предположим, игрок находится в восьми блоках, обе позиции в одном мире, а других смещений нет. Используйте SELF как SourceTarget относительного смещения и DIRECT_TARGET как DestinationTarget, затем поместите этот relativeOffset в Target2. Примеры описывают расстояние до конца луча; отрисованные точки также зависят от настроек луча.
Теперь применим относительное смещение:
Случай 1: normalize = false, multiplier = 1
- Исходное расстояние 8.
- Значение смещения становится
8 × 1 = 8. - Финальная длина луча:
8 + 8 = 16.
Луч пройдёт через игрока и продолжится ещё на 8 блоков.
Случай 2: normalize = false, multiplier = 2
- Значение смещения становится
8 × 2 = 16. - Финальная длина луча:
8 + 16 = 24.
Случай 3: normalize = true, multiplier = 1
- Расстояние нормализовано до 1.
- Значение смещения становится
1 × 1 = 1. - Финальная длина луча:
8 + 1 = 9.
Случай 4: normalize = true, multiplier = 2
- Значение смещения становится
1 × 2 = 2. - Финальная длина луча:
8 + 2 = 10.
Резюме
normalize = falseиспользует фактическое расстояние между целями.normalize = trueначинает с длины 1 для корректного ненулевого вектора.- Смещение всегда добавляется к исходному значению.
- Нулевой
multiplierубирает вычисленное смещение, только если оно конечно. Собственныйoffsetотносительного вектора всё ещё добавляется после этого, а обычныйoffsetцели остаётся отдельным. Чтобы отключить относительное смещение, удалите его блок.
Эта система позволяет легко расширять или сжимать расстояния динамически при построении более сложной логики навыков в скриптах EliteMobs.
Свойства
| Значение | Подробности | Обязательно? | Значение по умолчанию |
|---|---|---|---|
SourceTarget | Цель в точке, откуда будет начинаться вектор | ✅ | none |
DestinationTarget | Цель в конечной точке вектора | ✅ | none |
normalize | Определяет, должен ли вектор быть нормализован | ❌ | false |
multiplier | Умножает длину вектора. Вы можете рандомизировать это значение, используя ~. Пример: 1.0~2.5. | ❌ | 1.0 |
offset | Добавляет постоянный вектор после normalize и multiplier. Поддерживает диапазоны через ~, например 0~5,0~2,0~10. | ❌ | 0,0,0 |
relativeOffset и RelativeVector разбираются одним и тем же кодом и принимают одинаковые пять ключей.
Пример
eliteScript:
MakeStaticRay:
Events:
- EliteMobDamagedByPlayerEvent
Zone:
shape: STATIC_RAY
Target:
targetType: SELF
offset: 0,1,0
Target2:
targetType: DIRECT_TARGET
offset: 0,1,0
relativeOffset:
sourceTarget:
targetType: SELF
destinationTarget:
targetType: DIRECT_TARGET
multiplier: 5
normalize: true
Actions:
- action: SPAWN_PARTICLE
Target:
targetType: ZONE_FULL
particles:
- particle: ELECTRIC_SPARK
amount: 1
repeatEvery: 1
times: 400
Конец луча находится на пять блоков дальше игрока по линии от босса к игроку. Обычные смещения поднимают оба конца на блок над ногами; это не автоматический расчёт центров сущностей. STATIC_RAY обозначает форму, а не зафиксированные позиции целей: при стандартном track: true действие пересчитывает цели при повторах. Задайте Target.track: false в действии, чтобы кэшировать позиции луча для неподвижного отображения. Пример запрашивает 400 выполнений через один тик; каждый подходящий удар может начать ещё одну серию.
Примечание: Хотя этот пример использует относительное смещение на зоне, имейте в виду, что относительные смещения не ограничиваются зонами, их можно применять и к другим целям.