Lua-скриптинг: Мир и окружение
Эта страница описывает расширения context.world для боссов EliteMobs, а также context.vectors, context.settings и context.event. Они позволяют Lua-способностям создавать сущности, воспроизводить эффекты, запрашивать блоки и менять состояние мира. Новичкам стоит начать с раздела Начало работы.
Способности боссов используют Lua-песочницу MagmaCore. Их context.world создаётся на основе общей таблицы мира MagmaCore, поэтому координатные методы get_block_at(...), set_block_at(...) и spawn_particle(...) остаются доступны. Здесь описаны дополнения и переопределения EliteMobs для context.world, context.vectors, context.settings и context.event. Общий API мира описан в разделе Lua-движок MagmaCore.
При совпадении имён используется версия EliteMobs. Методы ниже сохраняют поведение EliteMobs, включая обход защиты создания молнии, расширенные параметры частиц и учёт временных блоков. Другие общие методы остаются доступны: get_entity(uuid), block_is_passable(x, y, z), location_is_protected(location), spawn_dust(...) и raycast(...). Их аргументы и поведение в незагруженных чанках приведены в общем справочнике API. Эти гарантии не распространяются автоматически на переопределения EliteMobs.
FreeMinecraftModels добавляет drop_elitemobs_procedural_loot, drop_elitemobs_random_loot, drop_elitemobs_custom_loot и start_elitemobs_transport в context.world только в собственных скриптах пропов. Каждый плагин содержит отдельную копию общей библиотеки скриптинга, поэтому эти методы не появляются в способностях боссов EliteMobs и скриптах NPC, даже если FreeMinecraftModels установлен. Способности боссов используют вместо них generate_player_loot и drop_bonus_coins.
context.world
Таблица world предоставляет методы создания сущностей, воспроизведения эффектов, изменения блоков и состояния мира. Они поддерживают двоеточие world:method() и точку без явного аргумента self.
Переопределения босса преобразуют таблицы местоположения с полями x, y, z, необязательными yaw/pitch и именем загруженного мира в world. Отсутствующие координаты равны 0; без мира используется текущий мир босса, но явно неизвестный мир приводит к неудаче преобразования. Допускается вложенная таблица current_location. nil или значение не в виде таблицы заменяется позицией босса. Общие методы сохраняют собственные правила преобразования и мир, зафиксированный при создании таблицы.
Закрытие Lua-экземпляра не отменяет изменения мира и не удаляет автоматически созданные сущности. Наблюдатели, принадлежащие скрипту, останавливаются, но независимые таймеры удаления сущностей, восстановление взрывов, усиленная молния и задачи золотых снарядов имеют собственный срок работы. Переопределения блоков и спавна не проверяют автоматически location_is_protected и загрузку чанков по правилам общего API. Проверяйте нужные ограничения перед изменением мира.
world:spawn_particle_at_location(location, particleSpec)
Создаёт частицы в указанном месте. Второй аргумент принимает имя частицы или таблицу параметров. Необязательный третий целочисленный аргумент задаёт количество, если amount отсутствует; по умолчанию 1. Перед поиском имена переводятся в верхний регистр. Неизвестное имя или неподдерживаемые данные вызывают предупреждение, частицы не создаются.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Куда спавнить частицы |
particleSpec | строка или таблица | Имя частицы или таблица параметров частиц (см. ниже) |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Simple particle by name
context.world:spawn_particle_at_location(context.boss:get_location(), "FLAME")
-- Full particle spec table with red dust
context.world:spawn_particle_at_location(context.boss:get_location(), {
particle = "DUST",
amount = 10,
x = 0.5,
y = 0.5,
z = 0.5,
speed = 0.02,
red = 255,
green = 0,
blue = 0,
})
end
}
Формат таблицы спецификации частиц
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
particle | string | обязательный | Имя частицы |
amount | int | 1 | Количество частиц |
x, y, z | number | 0 | Разброс/смещение по каждой оси |
speed | number | 0 | Скорость частиц |
red, green, blue | int | 255 | Цвет RGB для DUST и DUST_COLOR_TRANSITION |
toRed, toGreen, toBlue | int | 255 | Целевой цвет перехода для DUST_COLOR_TRANSITION |
Для DUST_COLOR_TRANSITION также допускаются ключи to_red, to_green, to_blue, но значения camelCase имеют приоритет. Размер обеих пылевых частиц фиксирован и равен 1; компоненты RGB должны быть в диапазоне 0..255. Другие частицы не получают дополнительных данных, поэтому метод поддерживает не все частицы, которым такие данные нужны.
В отличие от YAML EliteScript, имена частиц Lua не преобразуются из устаревших названий. Используйте текущие имена Spigot API: FIREWORK вместо FIREWORKS_SPARK, SMOKE вместо SMOKE_NORMAL, DUST вместо REDSTONE. Текущие и прежние названия приведены в списке допустимых частиц.
world:play_sound_at_location(location, sound, volume, pitch)
Воспроизводит звук в указанном месте.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
location | location table | Где воспроизвести звук | |
sound | string | Ключ звука Minecraft, например "entity.blaze.shoot", или имя перечисления Spigot Sound. Ключи из ресурс-пака тоже работают. | |
volume | number | 1.0 | Громкость |
pitch | number | 1.0 | Высота тона |
Пример
return {
api_version = 1,
on_spawn = function(context)
context.world:play_sound_at_location(
context.boss:get_location(),
"entity.wither.spawn",
1.0,
0.5
)
end
}
world:strike_lightning_at_location(location)
Создаёт настоящую молнию с уроном и включает обход защиты создания молнии EliteMobs. Это отличается от общего метода чисто визуальной молнии. Обход не гарантирует игнорирование всех правил урона и защиты других плагинов.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Куда бить |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("lightning", 100) then return end
context.world:strike_lightning_at_location(context.player:get_location())
context.player:send_message("&eA bolt of lightning strikes you!")
end
}
world:spawn_entity_at_location(entityType, location, options)
Создаёт ванильную сущность непосредственно в мире указанной позиции. Неизвестное имя возвращает nil; распознанный, но недоступный для создания тип всё ещё может вызвать ошибку. Метод не назначает автоматически стрелка снаряда и не регистрирует сущность как элитное подкрепление.
| Параметр | Тип | Примечания |
|---|---|---|
entityType | string | Имя типа сущности (например, "FIREBALL", "ARROW") |
location | location table | Где заспавнить |
options | table (optional) | Параметры спавна (см. ниже) |
Параметры спавна сущности
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
velocity | vector table | nil | Начальная скорость {x, y, z} |
effect | string | nil | EntityEffect, проигрываемый при спавне |
duration | int | 0 | Положительное значение задаёт удаление через указанное число тиков; неположительное не создаёт таймер удаления |
on_land | function | nil | function(land_location, entity_ref) при касании земли, недействительности сущности или превышении max_ticks; это не событие попадания снаряда и не доказательство приземления |
max_ticks | int | 6000 | Максимум тиков наблюдения до принудительного вызова on_land |
persistent | boolean | Значение Minecraft по умолчанию | false исключает сущность из сохранения чанка, поэтому остановка сервера или выгрузка чанка посреди эффекта не оставит её в мире |
Возвращает таблицу-обёртку сущности. Неживые сущности, например FIREBALL, ARROW и TNT, используют
обёртку ссылки на неживую сущность, где is_valid() является методом.
Живые сущности, например ZOMBIE и GIANT, используют полную
обёртку живой сущности, где is_valid является булевым полем.
Вызов entity:is_valid() у такой обёртки приводит к attempt to call a boolean value.
Наблюдатель приземления проверяет сущность каждый тик, пока скрипт активен, и останавливается вместе с его задачами. Таймер положительного duration независим и может удалить сущность после закрытия скрипта. Неизвестные имена effect игнорируются.
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("fireball_spawn", 100) then return end
-- Spawn a fireball aimed at the player
local boss_loc = context.boss:get_location()
local dir = context.vectors.get_vector_between_locations(boss_loc, context.player:get_location())
dir = context.vectors.normalize_vector(dir)
context.world:spawn_entity_at_location("FIREBALL", boss_loc, {
velocity = { x = dir.x * 2, y = dir.y * 2, z = dir.z * 2 },
duration = 100,
})
end
}
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Spawn a primed TNT with a landing callback
context.world:spawn_entity_at_location("TNT", context.boss:get_location(), {
velocity = { x = 0, y = 1.5, z = 0 },
on_land = function(land_location, entity_ref)
context.world:spawn_particle_at_location(land_location, {
particle = "EXPLOSION_EMITTER",
amount = 1,
})
end,
})
end
}
world:spawn_display_at_location(location, options)
Создаёт display предмета или блока: парящий визуальный элемент без хитбокса, гравитации и ИИ. Используйте его для вращающихся камней, брошенных объектов и других эффектов, которые нужно только видеть, вместо оформления стойки для брони. Display центрируется на location и поворачивается по его yaw.
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
item | string | Материал, показываемый как предмет. Блочный предмет, например "AMETHYST_BLOCK", отображается как блок по центру | |
block | string | Блок, показываемый как блочный display, в виде материала или данных блока, например "lantern[hanging=true]" | |
scale | number или vector table | 1 | Число масштабирует все оси; {x, y, z} масштабирует каждую отдельно. При 1 блок имеет ширину в один блок |
duration | int | 0 | Положительные значения удаляют display через указанное число тиков |
teleport_duration | int | 0 | Сколько тиков клиент плавно перемещает display в каждое новое положение, от 0 до 59. Используйте 1, если вы телепортируете display каждый тик |
billboard | string | FIXED | FIXED, VERTICAL, HORIZONTAL или CENTER |
glowing | boolean | false | Контурное свечение |
brightness | int | освещённость мира | От 0 до 15, переопределяет освещённость в месте display |
bedrock_fallback | boolean | true | См. ниже |
Укажите ровно одно из item или block. Отсутствующее или неизвестное значение item или block, оба сразу или неположительный scale возвращают nil и записывают предупреждение с названием способности. Неизвестное значение billboard оставляет FIXED.
Display-сущности никогда не сохраняются вместе с чанком. Они удаляются, когда истекает duration, когда вы вызываете remove() или когда способность завершает работу, смотря что наступит раньше.
Клиенты Bedrock не умеют отображать display-сущности. Игроки Bedrock, находящиеся в мире в момент появления display, вместо этого видят невидимую стойку для брони с тем же предметом (для блочного display — с предметом этого блока), а сам display от них скрыт. Стойка следует за display и удаляется вместе с ним. Игроки Bedrock, которые заходят в мир позже, стойку не получают, а блок без предметной формы, например fire, не получает стойки вообще. Отключите это через bedrock_fallback = false для эффектов, которые игрокам Bedrock видеть не нужно.
Возвращаемая обёртка содержит uuid и entity_type и такие методы:
| Метод | Примечания |
|---|---|
is_valid(), is_alive() | Существует ли display ещё |
get_location() | Текущее местоположение |
teleport_to_location(location) | Перемещает display и его стойку Bedrock |
remove() | Удаляет display и его стойку Bedrock |
set_scale(scale) | Те же значения, что у параметра scale |
set_item(material) | Только для предметных display; иначе возвращает false |
set_block(block) | Только для блочных display; иначе возвращает false |
set_glowing(enabled) | Контурное свечение |
set_brightness(level) | От 0 до 15 или nil, чтобы снова использовать освещённость мира |
set_teleport_duration(ticks) | То же, что параметр teleport_duration |
Пример
-- Three amethyst stones circle the target for three seconds.
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil or not context.cooldowns:check_local("orbit", 200) then return end
local target = context.player
local stones = {}
for i = 1, 3 do
stones[i] = context.world:spawn_display_at_location(target:get_location(), {
item = "AMETHYST_BLOCK", scale = 0.3, duration = 60, teleport_duration = 1
})
end
local elapsed = 0
local task
task = context.scheduler:run_every(1, function(context)
elapsed = elapsed + 1
if elapsed >= 60 then
context.scheduler:cancel_task(task)
return
end
local center = target:get_location()
for i = 1, 3 do
local angle = elapsed * 0.2 + i * (2 * math.pi / 3)
if stones[i] ~= nil and stones[i]:is_valid() then
stones[i]:teleport_to_location(em.create_location(
center.x + math.cos(angle) * 1.5, center.y + 1.2, center.z + math.sin(angle) * 1.5, center.world, 0, 0))
end
end
end)
end
}
world:spawn_falling_block_at_location(location, material, options)
Создаёт падающий блок из блочного материала. При наличии on_land EliteMobs перехватывает событие изменения блока, отменяет установку и один раз вызывает function(land_location, entity_ref). Без обработчика блок может установиться обычным образом. Метод не имеет параметров duration или max_ticks и не вызывает обработчик из-за недействительности сущности или истечения времени.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Где заспавнить |
material | string | Имя материала (например, "STONE", "MAGMA_BLOCK") |
options | table (optional) | Параметры спавна (см. ниже) |
Параметры падающего блока
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
velocity | vector table | nil | Начальная скорость {x, y, z} |
drop_item | boolean | false | Выпадает ли блок в виде предмета |
hurt_entities | boolean | false | Наносит ли блок урон сущностям, на которые падает |
on_land | function | nil | Обратный вызов function(land_location, entity_ref) при приземлении блока |
Возвращает обёртку неживой сущности или nil, если позиция либо материал не распознаны. Известный материал, не являющийся блоком, всё ещё может вызвать ошибку при создании данных блока.
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Rain magma blocks from above
local loc = context.boss:get_location()
for i = 1, 5 do
local offset_loc = {
x = loc.x + math.random(-3, 3),
y = loc.y + 10,
z = loc.z + math.random(-3, 3),
world = loc.world
}
context.world:spawn_falling_block_at_location(offset_loc, "MAGMA_BLOCK", {
velocity = { x = 0, y = -0.5, z = 0 },
hurt_entities = true,
on_land = function(land_location, entity_ref)
context.world:spawn_particle_at_location(land_location, { particle = "LAVA", amount = 8 })
end,
})
end
end
}
world:spawn_custom_boss_at_location(filename, location, options)
Порождает кастомного босса EliteMobs из конфигурационного файла.
| Параметр | Тип | Примечания |
|---|---|---|
filename | string | Имя конфигурационного файла босса (например, "my_boss.yml") |
location | location table | Где заспавнить |
options | table (optional) | Параметры спавна (см. ниже) |
Параметры спавна кастомного босса
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
level | int | Собственная конфигурация или динамические правила уровня создаваемого босса | Переопределяет уровень; без параметра уровень заклинателя не наследуется |
silent | boolean | false | Подавляет сообщения о спавне |
velocity | vector table | nil | Начальная скорость |
add_as_reinforcement | boolean | false | Регистрирует как подкрепление текущего босса |
Возвращает таблицу-обёртку сущности либо nil, если босса создать не удалось.
Пример
return {
api_version = 1,
on_enter_combat = function(context)
local minion = context.world:spawn_custom_boss_at_location(
"skeleton_minion.yml",
context.boss:get_location(),
{ level = 10, add_as_reinforcement = true }
)
if minion ~= nil then
context.boss:send_message("&cMinions, arise!")
end
end
}
world:spawn_boss_at_location(filename, location, level)
Более простой метод создания босса. Пропущенные позиция и уровень берутся у босса, вызвавшего метод. Результат не регистрируется как подкрепление. Для уровня по умолчанию пропустите третий аргумент; явный nil в нём не принимается.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
filename | string | Имя конфигурационного файла босса | |
location | location table | местоположение босса | Где заспавнить (необязательно, по умолчанию — местоположение босса) |
level | int | уровень босса | Переопределяет уровень спавна (необязательно) |
Возвращает таблицу-обёртку сущности или nil.
Пример
return {
api_version = 1,
on_enter_combat = function(context)
context.world:spawn_boss_at_location("zombie_guard.yml", context.boss:get_location(), 5)
context.boss:send_message("&cGuards, defend me!")
end
}
world:spawn_reinforcement_at_location(filename, location, duration, velocity)
Создаёт подкрепление без сообщений через систему EliteMobs, записывает призывателя и наследует нормализованный бой, если он включён у кастомного босса-призывателя. Уровень определяют собственная конфигурация подкрепления и динамические правила. duration задаёт таймер ухода, а не уровень.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
filename | string | Имя конфигурационного файла босса | |
location | location table | Где заспавнить | |
duration | int | 0 | Число тиков до ухода; 0 отключает таймер |
velocity | vector table | nil | Начальная скорость (необязательно) |
Возвращает таблицу-обёртку сущности или nil.
Пример
return {
api_version = 1,
on_enter_combat = function(context)
context.world:spawn_reinforcement_at_location(
"necro_skeleton.yml",
context.boss:get_location(),
0,
{ x = 0, y = 0.5, z = 0 }
)
context.boss:send_message("&5Rise, my servant!")
end
}
world:spawn_fireworks_at_location(location, spec)
Создаёт настоящий фейерверк без автоматического отключения урона. Укажите хотя бы один допустимый цвет для каждого эффекта; создание эффекта без цветов может завершиться ошибкой.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Где заспавнить |
spec | table | Спецификация фейерверка (см. ниже) |
Таблица спецификации фейерверка
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
power | int | 1 | Мощность полёта (высота) |
velocity | vector table | nil | Начальная скорость |
shot_at_angle | boolean | true | Запускается ли фейерверк под углом (используется, когда задана скорость) |
effects | table of tables | nil | Массив спецификаций эффектов фейерверка. Если не указан, спецификация верхнего уровня считается одним эффектом. |
Спецификация эффекта фейерверка
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
type | string | "BALL_LARGE" | "BALL", "BALL_LARGE", "STAR", "BURST", "CREEPER" |
flicker | boolean | true | Эффект мерцания |
trail | boolean | true | Эффект следа |
colors | table | Обязателен для каждого эффекта | Непустой массив имён цветов или таблиц {red = 255, green = 0, blue = 0} |
fade_colors | table | nil | Массив имён цветов затухания или таблиц {red, green, blue} |
Имена цветов: "WHITE", "SILVER", "GRAY", "BLACK", "RED", "MAROON", "YELLOW", "OLIVE", "LIME", "GREEN", "AQUA", "TEAL", "BLUE", "NAVY", "FUCHSIA", "PURPLE", "ORANGE"
Возвращает обёртку неживой сущности или nil, если позиция не распознана. :detonate() запрашивает взрыв. Тип и имена цветов не учитывают регистр; неизвестный тип заменяется на BALL_LARGE, неизвестный цвет на белый. Значения RGB должны быть в диапазоне 0..255.
Пример
return {
api_version = 1,
on_spawn = function(context)
local fw = context.world:spawn_fireworks_at_location(context.boss:get_location(), {
power = 0,
effects = {
{
type = "STAR",
flicker = true,
trail = true,
colors = { "RED", "ORANGE", { red = 255, green = 200, blue = 0 } },
fade_colors = { "YELLOW" },
},
},
})
if fw == nil then return end
-- Detonate on the next tick for a visual burst
context.scheduler:run_after(1, function()
fw:detonate()
end)
end
}
world:spawn_splash_potion_at_location(location, spec)
Создаёт настоящее брошенное взрывное зелье. Неизвестные имена эффектов Bukkit вызывают предупреждение и пропускаются. Метод не назначает стрелка и не применяет фильтр эффектов подземелья, используемый прямыми методами зелий босса. Действуют обычные правила взрывного зелья.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Где заспавнить |
spec | table | Спецификация зелья (см. ниже) |
Таблица спецификации взрывного зелья
| Ключ | Тип | Примечания |
|---|---|---|
velocity | vector table | Начальная скорость брошенного зелья |
effects | table of tables | Массив спецификаций эффектов зелья |
Спецификация эффекта зелья
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
type | string | обязательный | Имя типа эффекта зелья (например, "SLOWNESS", "POISON") |
duration | int | 0 | Длительность в тиках |
amplifier | int | 0 | Усилитель эффекта (0 = уровень I) |
overwrite | boolean | true | Заменяет ранее добавленный эффект того же типа в метаданных этого зелья; не задаёт правила для эффектов, уже действующих на игрока |
Возвращает таблицу-ссылку на сущность или nil.
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("potion_throw", 200) then return end
local dir = context.vectors.get_vector_between_locations(
context.boss:get_location(),
context.player:get_location()
)
dir = context.vectors.normalize_vector(dir)
context.world:spawn_splash_potion_at_location(context.boss:get_location(), {
velocity = { x = dir.x * 1.5, y = 0.5, z = dir.z * 1.5 },
effects = {
{ type = "SLOWNESS", duration = 100, amplifier = 1 },
{ type = "WEAKNESS", duration = 60, amplifier = 0 },
},
})
end
}
world:place_temporary_block_at_location(location, material, duration, requireAir)
Устанавливает отслеживаемый блок и при положительном сроке восстанавливает его прежние данные. Содержимое контейнера не сохраняется. Исходный блок возвращается по окончании таймера, при выгрузке чанка или мира либо при выключении плагина, но только если на месте всё ещё стоит временный блок, поэтому более поздняя правка не перезаписывается. Повторная установка на блок, где всё ещё стоит временный блок, перезапускает его таймер и сохраняет первый сохранённый оригинал. Блоки с сущностями блоков, например сундуки и таблички, незагруженные чанки и блоки, удерживаемые другим владельцем временных блоков, пропускаются. Разрушение отслеживаемого блока ничего не выбрасывает и прекращает отслеживание без восстановления. Используйте блочный материал. Это переопределение босса возвращает nil, в том числе когда установке препятствует requireAir или пропуск; оно не сообщает об успехе и не проверяет защиту региона автоматически.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
location | location table | Куда поставить | |
material | string | Имя материала | |
duration | int | 0 | Тики до восстановления; 0 или отрицательное значение ставит блок навсегда без отслеживания |
requireAir | boolean | false | Если true, ставит только если блок сейчас воздух |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Create a temporary ice floor under the boss
local loc = context.boss:get_location()
for dx = -2, 2 do
for dz = -2, 2 do
context.world:place_temporary_block_at_location(
{ x = loc.x + dx, y = loc.y - 1, z = loc.z + dz, world = loc.world },
"PACKED_ICE",
100,
false
)
end
end
end
}
world:set_block_at_location(location, material, requireAir)
Устанавливает блок навсегда через менеджер временных блоков, без таймера восстановления и без отслеживания, поэтому изменение сохраняется после выключения плагина. Если на месте стоит временный блок с таймером, он перестаёт отслеживаться и не восстанавливается. Блоки, удерживаемые другим владельцем временных блоков, остаются без изменений. Для восстановления по таймеру используйте place_temporary_block_at_location с положительным сроком.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
location | location table | Куда поставить | |
material | string | Имя материала | |
requireAir | boolean | false | Если true, ставит только если блок сейчас воздух |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Place fire at the boss's location
context.world:set_block_at_location(context.boss:get_location(), "FIRE", true)
end
}
world:get_block_type_at_location(location)
Возвращает имя материала в верхнем регистре или nil, если позиция не распознана. В отличие от общего координатного запроса, это переопределение обращается к блоку напрямую, без проверки загрузки чанка.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
local block_type = context.world:get_block_type_at_location(context.boss:get_location())
if block_type == "WATER" then
context.boss:send_message("&bThe boss is empowered by water!")
context.boss:apply_potion_effect("SPEED", 200, 1)
end
end
}
world:get_highest_block_y_at_location(location)
Возвращает Y самого высокого блока по данным Bukkit или nil, если позиция не распознана. Не проверяет, загружен ли чанк и безопасна ли точка для телепортации.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса (используются X и Z) |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("skyport", 200) then return end
local loc = context.player:get_location()
local ground_y = context.world:get_highest_block_y_at_location(loc)
-- Teleport the player to the surface
context.player:teleport_to_location({
x = loc.x, y = ground_y + 1, z = loc.z, world = loc.world
})
context.player:send_message("&eYou are teleported to the surface!")
end
}
world:get_blast_resistance_at_location(location)
Возвращает взрывоустойчивость материала в указанном месте или 0, если позиция не распознана.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
local resistance = context.world:get_blast_resistance_at_location(context.boss:get_location())
context.log:info("Blast resistance at boss: " .. resistance)
end
}
world:is_air_at_location(location)
Возвращает true, если блок в указанном месте — воздух.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
local loc = context.boss:get_location()
local above = { x = loc.x, y = loc.y + 2, z = loc.z, world = loc.world }
if context.world:is_air_at_location(above) then
-- There is space above the boss, launch upward
context.boss:set_velocity_vector({ x = 0, y = 1.5, z = 0 })
end
end
}
world:is_passable_at_location(location)
Возвращает результат Bukkit Block.isPassable() или false, если позиция не распознана. Это запрос одного блока, а не проверка того, помещается ли целая сущность и может ли она пройти по маршруту.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
if context.world:is_passable_at_location(context.boss:get_location()) then
context.log:info("Boss is in a passable block")
end
end
}
world:is_passthrough_at_location(location)
Возвращает true, если блок в указанном месте не твёрдый (похоже на проходимость, но на основе проверки твёрдости).
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
local loc = context.boss:get_location()
local above = { x = loc.x, y = loc.y + 1, z = loc.z, world = loc.world }
if context.world:is_passthrough_at_location(above) then
context.log:info("Boss can move upward")
end
end
}
world:is_on_floor_at_location(location)
Возвращает true, если блок в указанной позиции нетвёрдый, а блок на единицу Y ниже твёрдый. Не проверяет состояние приземления сущности, её габариты или свободное место над головой.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
if context.world:is_on_floor_at_location(context.boss:get_location()) then
context.boss:send_message("&aThe boss slams the ground!")
context.world:spawn_particle_at_location(context.boss:get_location(), {
particle = "CLOUD",
amount = 30,
})
end
end
}
world:is_standing_on_material(location, material)
Возвращает true, если блок непосредственно под указанным местом соответствует заданному материалу.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Местоположение для запроса |
material | string | Имя материала для проверки |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if context.world:is_standing_on_material(context.player:get_location(), "SOUL_SAND") then
context.player:send_message("&8The soul sand saps your strength!")
context.player:apply_potion_effect("SLOWNESS", 60, 2)
end
end
}
world:set_world_time(time) / world:set_world_time(location, time)
Задаёт время во всём мире. Необязательное местоположение позволяет выбрать мир. При закрытии скрипта прежнее время не восстанавливается.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table (optional) | На какой мир воздействовать. По умолчанию — мир босса. |
time | int | Время мира в тиках (0 = рассвет, 6000 = полдень, 13000 = ночь, 18000 = полночь) |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Set to midnight when combat starts
context.world:set_world_time(18000)
context.boss:send_message("&8Darkness falls...")
end
}
world:set_world_weather(weather, duration) / world:set_world_weather(location, weather, duration)
Задаёт погоду в мире босса или необязательного местоположения. Имена не учитывают регистр; неизвестные имена лишь вызывают предупреждение. RAIN/CLEAR задают таймер погоды, а THUNDER таймер грозы. Изменение действует на весь мир и не отменяется при закрытии скрипта.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
location | location table (optional) | мир босса | На какой мир воздействовать |
weather | string | "CLEAR", "RAIN" (или "PRECIPITATION"), "THUNDER" | |
duration | int | 6000 | Длительность погоды в тиках |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Start a thunderstorm for 200 ticks
context.world:set_world_weather("THUNDER", 200)
context.boss:send_message("&eA storm gathers!")
end
}
world:generate_fake_explosion(blockLocations, sourceLocation)
Удаляет настоящие блоки и создаёт обломки из падающих блоков через систему восстановления взрывов EliteMobs. Обломки могут наносить урон сущностям, поэтому это не безвредные частицы. Требуется включённый doExplosionRegen; при передаче исходной позиции проверяется флаг восстановления взрывов WorldGuard. Воздух, огонь, жидкости и отслеживаемые временные блоки пропускаются; зависимые соседние блоки тоже могут попасть в список. Восстановление начинается через 1200 тиков и обрабатывает один записанный блок за тик. Все входные позиции должны быть в мире босса. Операция возвращает nil и не отменяется при закрытии скрипта.
| Параметр | Тип | Примечания |
|---|---|---|
blockLocations | table of location tables | Массив местоположений блоков для «взрыва» |
sourceLocation | location table (optional) | Источник взрыва для расчёта направления |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
local loc = context.boss:get_location()
local blocks = {}
for dx = -1, 1 do
for dz = -1, 1 do
table.insert(blocks, { x = loc.x + dx, y = loc.y, z = loc.z + dz, world = loc.world })
end
end
context.world:generate_fake_explosion(blocks, loc)
end
}
world:run_console_command(command)
Немедленно выполняет консольную команду от имени сервера и возвращает nil, не предоставляя результат её успешности. Плейсхолдеры игрока и босса автоматически не подставляются.
Ванильные команды сообщают свой результат, а при значении по умолчанию broadcast-console-to-ops=true сервер показывает каждый результат всем операторам онлайн. Часто выполняемые команды, например data merge entity, kill или damage, засоряют им чат. Используйте вместо них нативные методы: spawn_display_at_location для визуальных эффектов, методы стоек для брони для стоек, entity:remove() для удаления того, что заспавнил скрипт, и entity:deal_custom_damage(amount) для точного урона от босса.
| Параметр | Тип | Примечания |
|---|---|---|
command | string | Команда для выполнения (без ведущего /) |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
context.world:run_console_command("say The boss has entered phase 2!")
end
}
world:run_empowered_lightning_task_at_location(location)
Запускает независимую задачу Bukkit в сохранённой позиции. Она выпускает SOUL_FIRE_FLAME в течение 60 итераций, затем создаёт настоящую молнию с обходом защиты спавна и направленный вниз огненный шар с силой взрыва 5 и меткой ender_dragon_empowered_lightning.yml. Это атака с уроном. Закрытие или приостановка Lua-скрипта не отменяет задачу; метод также не проверяет настройку предупреждающих эффектов.
| Параметр | Тип | Примечания |
|---|---|---|
location | location table | Куда бить |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
context.world:run_empowered_lightning_task_at_location(context.boss:get_location())
context.boss:send_message("&eFeel the power of the storm!")
end
}
world:spawn_fake_gold_nugget_at_location(location, velocity, hasGravity)
Показывает ближайшим игрокам золотой самородок через пакеты; игроки и воронки не могут его подобрать. Само создание не запускает движение и урон. Передайте его в run_fake_gold_nugget_damage один раз в составе группы либо удалите явно.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
location | location table | Местоположение спавна | |
velocity | vector table | Начальная скорость | |
hasGravity | boolean | false | Действует ли на снаряд гравитация |
Возвращает таблицу фиктивного снаряда или nil, если позиция либо вектор не распознаны. Методы: get_location(), set_gravity(bool), remove(), is_removed().
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("nugget", 60) then return end
local dir = context.vectors.get_vector_between_locations(
context.boss:get_location(),
context.player:get_location()
)
dir = context.vectors.normalize_vector(dir)
local nugget = context.world:spawn_fake_gold_nugget_at_location(
context.boss:get_location(),
{ x = dir.x, y = dir.y, z = dir.z }
)
if nugget ~= nil then
context.world:run_fake_gold_nugget_damage({ nugget })
end
end
}
world:run_fake_gold_nugget_damage(projectiles)
Запускает независимую задачу Bukkit, которая каждый тик перемещает и проверяет группу снарядов. Вызывайте один раз на группу: каждый вызов создаёт новую задачу. В новой позиции ищутся живые сущности в прямоугольной области с полуразмером 0.5. Исходный босс и блокирующие игроки пропускаются, остальным отправляется пользовательский урон 1 по правилам урона босса. Столкновение может удалить снаряд даже при отклонённом уроне. Касание земли или предел в 100 тиков также удаляют его. Это проверка отдельных позиций, а не непрерывного луча; закрытие или приостановка Lua-экземпляра не отменяет задачу.
| Параметр | Тип | Примечания |
|---|---|---|
projectiles | table | Массив таблиц фиктивных снарядов из spawn_fake_gold_nugget_at_location |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
-- Keep this batch separate from later combat entries.
local projectiles = {}
local loc = context.boss:get_location()
for i = 1, 5 do
local angle = (i / 5) * math.pi * 2
local nugget = context.world:spawn_fake_gold_nugget_at_location(
loc,
{ x = math.cos(angle) * 0.5, y = 0.3, z = math.sin(angle) * 0.5 }
)
if nugget ~= nil then table.insert(projectiles, nugget) end
end
-- Start the batch once; the helper runs its own per-tick task.
context.world:run_fake_gold_nugget_damage(projectiles)
-- Remove any surviving projectiles after 3 seconds.
context.scheduler:run_after(60, function()
for _, projectile in ipairs(projectiles) do
projectile:remove()
end
end)
end
}
world:generate_player_loot(times)
Запускает обычный генератор добычи игроков times раз; неположительные значения ничего не делают. Требуются eliteLoot, отсутствие сработавшей защиты от эксплуатации, загруженные данные игрока и записанный урон не менее 10% максимального здоровья босса. Игроки с блокировкой наград подземелья пропускаются. Каждый проход может выдавать монеты, а при включённой случайной добыче также случайные или особые предметы и свитки по обычным настройкам и правилам группы. Метод не повторяет все заданные автором кастомные выпадения и не гарантирует предмет за каждый проход. Повторные вызовы добавляют попытки выдачи наград; ограничения одним вызовом на босса нет.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
times | int | 1 | Количество розыгрышей добычи |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
local pct = context.boss:get_health() / context.boss:get_maximum_health()
if pct < 0.5 and not context.boss:has_tag("bonus_loot") then
context.boss:add_tag("bonus_loot")
context.world:generate_player_loot(2)
context.boss:send_message("&6Bonus loot drops!")
end
end
}
world:drop_bonus_coins(multiplier)
Создаёт дополнительные монеты для подходящих игроков с записанным уроном строго больше 10% максимального здоровья босса. NPC и игроки без загруженных данных пропускаются. Награда зависит от уровня наград босса и multiplier.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
multiplier | number | 2.0 | Множитель количества монет |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
local pct = context.boss:get_health() / context.boss:get_maximum_health()
if pct < 0.25 and not context.boss:has_tag("bonus_coins") then
context.boss:add_tag("bonus_coins")
context.world:drop_bonus_coins(3.0)
context.boss:send_message("&6Gold spills everywhere!")
end
end
}
context.vectors
Функции векторной математики поддерживают точку, как в примерах, и двоеточие. Входные данные принимают именованные поля x, y, z, числовые индексы 1..3 или вложенную таблицу direction. Отсутствующие компоненты равны 0. Результат возвращается новой таблицей, входные данные не меняются.
| Метод | Возвращает | Примечания |
|---|---|---|
vectors.get_vector_between_locations(loc1, loc2[, options]) | таблица вектора | Смещение loc2 - loc1, по умолчанию без нормализации |
vectors.normalize_vector(vec) | таблица вектора | Единичный вектор для ненулевого входа; нулевой остаётся нулевым |
vectors.rotate_vector(vec, pitch, yaw) | таблица вектора | Поворот в градусах сначала вокруг мировой оси X, затем Y |
У всех таблиц векторов есть поля x, y, z.
vectors.get_vector_between_locations(loc1, loc2, options)
| Параметр | Тип | Примечания |
|---|---|---|
loc1 | location table | Начальная точка |
loc2 | location table | Конечная точка |
options | table (optional) | Параметры постобработки (см. ниже) |
Параметры вектора
| Ключ | Тип | По умолчанию | Примечания |
|---|---|---|---|
normalize | boolean | false | Нормализовать полученный вектор |
multiplier | number | 1.0 | Масштабировать вектор |
offset | vector table | nil | Добавить вектор смещения |
Параметры применяются по порядку: нормализация ненулевого смещения, умножение, затем добавление смещения по мировым осям. Нераспознанные позиции и разные миры дают нулевой вектор до применения параметров. Для совпадающих корректных позиций смещение всё ещё может применяться.
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("dash", 100) then return end
-- Compute a normalized direction from boss to player, scaled to speed 2
local dir = context.vectors.get_vector_between_locations(
context.boss:get_location(),
context.player:get_location(),
{ normalize = true, multiplier = 2.0 }
)
-- Launch the boss toward the player
context.boss:set_velocity_vector(dir)
end
}
vectors.normalize_vector(vec)
| Параметр | Тип | Примечания |
|---|---|---|
vec | vector table | Входной вектор |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
local raw = context.vectors.get_vector_between_locations(
context.boss:get_location(),
context.player:get_location()
)
local unit = context.vectors.normalize_vector(raw)
context.log:info("Direction: " .. unit.x .. ", " .. unit.y .. ", " .. unit.z)
end
}
vectors.rotate_vector(vec, pitch, yaw)
| Параметр | Тип | Примечания |
|---|---|---|
vec | vector table | Входной вектор |
pitch | number | Поворот вокруг оси X в градусах |
yaw | number | Поворот вокруг оси Y в градусах |
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("spread_shot", 100) then return end
local forward = context.vectors.normalize_vector(
context.vectors.get_vector_between_locations(
context.boss:get_location(),
context.player:get_location()
)
)
-- Fire three fireballs in a spread pattern
for _, yaw_offset in ipairs({ -30, 0, 30 }) do
local dir = context.vectors.rotate_vector(forward, 0, yaw_offset)
context.boss:summon_projectile(
"FIREBALL",
context.boss:get_eye_location(),
{
x = context.boss:get_location().x + dir.x * 10,
y = context.boss:get_location().y + dir.y * 10,
z = context.boss:get_location().z + dir.z * 10,
world = context.boss:get_location().world
},
1.0
)
end
end
}
Веер направлений можно построить, поворачивая базовый вектор в цикле:
local base = context.vectors.normalize_vector(
context.vectors.get_vector_between_locations(boss_loc, target_loc)
)
for angle = 0, 330, 30 do
local dir = context.vectors.rotate_vector(base, 0, angle)
-- Use dir for spawning projectiles in a ring
end
context.settings
Доступ только для чтения к настройкам способностей. Метод читает текущее значение при вызове и не отключает частицы или другие эффекты автоматически. Скрипт должен использовать результат, чтобы решить, показывать ли предупреждение.
| Метод | Возвращает | Примечания |
|---|---|---|
settings:warning_visual_effects_enabled() | boolean | Включены ли предупреждающие визуальные эффекты в настройках боя мобов |
Пример
return {
api_version = 1,
on_enter_combat = function(context)
if context.settings:warning_visual_effects_enabled() then
context.world:spawn_particle_at_location(context.boss:get_location(), {
particle = "DUST",
amount = 20,
red = 255, green = 0, blue = 0,
})
end
end
}
context.event
Данные текущего события. Доступные поля зависят от исходного события, поэтому проверяйте необязательные поля. Числовые методы изменения урона требуют точки, например event.set_damage_amount(value); transfer_damage поддерживает и точку, и двоеточие. Таблица события босса не предоставляет общие члены cancel, uncancel или is_cancelled.
| Поле или метод | Когда доступно | Примечания |
|---|---|---|
event.damage_amount | Хуки урона | Снимок урона при первом разрешении лениво создаваемой таблицы события |
event.get_damage_amount() | Хуки урона | Читает текущую величину после изменений |
event.damage_cause | Хуки урона | Имя перечисления Bukkit DamageCause (например, "ENTITY_ATTACK") |
event.cancel_event() | Отменяемые события | Отменяет событие |
event.set_damage_amount(value) | Хуки на основе EliteDamageEvent | Задаёт урон напрямую |
event.multiply_damage_amount(multiplier) | Хуки на основе EliteDamageEvent | Умножает текущий урон |
event.damager | События урона с сущностью, наносящей урон | Обёртка исходного источника Bukkit; при попадании снаряда это сам снаряд, а не стрелок |
event.projectile | События урона, где урон наносит снаряд | Обёртка-ссылка на сущность-снаряд |
event.spawn_reason | on_spawn | Имя перечисления причины спавна |
event.entity | Урон игрока по боссу, on_death, события зон | Повреждённый босс, погибшая сущность или сущность, пересекающая зону; при уроне подкреплению это подкрепление |
event.is_damage_transfer | Урон игрока по боссу, включая передачу от подкрепления | Создан ли этот удар переносом урона |
event:transfer_damage(target, amount) | Урон игрока по боссу, включая передачу от подкрепления | Отправляет отдельный удар другой подходящей элитной сущности; см. правила переноса урона |
Пример: уменьшение входящего урона вдвое
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.event ~= nil then
local dmg = context.event.damage_amount
context.log:info("Boss took " .. dmg .. " damage, halving it")
context.event.multiply_damage_amount(0.5)
end
end
}
Пример: отмена урона от снарядов
Пример
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.event ~= nil and context.event.damage_cause == "PROJECTILE" then
context.event.cancel_event()
if context.player ~= nil then
context.player:send_message("&cThe boss deflects your projectile!")
end
end
end
}
Пример: чтение причины урона
Пример
return {
api_version = 1,
on_player_damaged_by_boss = function(context)
if context.event ~= nil then
context.log:info("Damage cause: " .. (context.event.damage_cause or "unknown"))
end
end
}
damage_amount— это снимок. Он не обновляется автоматически после вызоваset_damage_amount()илиmultiply_damage_amount().- В новом контексте запланированного обработчика
event = nil. Сохранение старого контекста хука не позволяет корректно менять уже завершённое событие; изменяйте его во время выполнения хука. - Методы урона меняют ожидающее событие, а не уже потерянное здоровье. Последующие слушатели могут изменить или отменить удар. Успешный перенос отправляет дополнительный удар и не уменьшает и не отменяет исходный автоматически.
