跳至主要内容

Lua 腳本:區域與目標選擇

webapp_banner.jpg

EliteMobs 的 Lua 功能提供了兩種互補的方法來定義空間區域和解析目標:

  • 原生區域 (context.zones) -- 簡單直接。將區域定義構建為普通的 Lua 表,然後查詢實體或位置。最適合簡單的「這個區域內有東西嗎?」檢查。
  • 腳本工具 (context.script) -- 更豐富的目標選擇,帶有 watch/contains/entities 方法的區域控制碼,粒子生成、傷害和推動動作。使用與 EliteScript 區域EliteScript 目標相同的欄位名稱以便於熟悉。

兩種方法都是原生 Lua API。選擇適合你能力複雜度的方法。


原生區域:context.zones

原生區域讓你將區域定義為普通的 Lua 表並直接查詢。沒有控制碼,沒有額外抽象 -- 只是一個描述形狀的表和一個查詢它的方法呼叫。

方法

方法說明
zones:get_entities_in_zone(zoneDef, options)傳回區域內實體包裝器的陣列
zones:get_locations_in_zone(zoneDef, options)傳回區域內位置表的陣列
zones:zone_contains(zoneDef, location[, "full"|"border"])如果位置在區域內則傳回 true
zones:watch_zone(zoneDef, callbacks, options)註冊一個每 tick 觸發的持久區域觀察器

區域定義欄位

欄位類型說明
kindstring"sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray"
radiusnumber區域半徑(sphere、dome、cylinder、cone)
heightnumber圓柱體高度
originlocation中心位置(省略時預設為 Boss 位置)
destinationlocation射線和錐體的終點
x, y, znumber長方體半尺寸
lengthnumber錐體和射線的長度
thickness / point_radiusnumber射線粗細
border_radiusnumber邊界寬度(預設 1
x_border, y_border, z_bordernumber長方體邊界寬度(預設 1
animation_durationint動畫射線的動畫長度(tick 為單位)
pitch_pre_rotation, yaw_pre_rotationnumber預旋轉角度(旋轉射線)
pitch_rotation, yaw_rotationnumber每 tick 旋轉角度(旋轉射線)
origin_end, destination_endlocation平移射線的結束位置
ignores_solid_blocksboolean射線是否穿過實體方塊(預設 true

查詢選項

說明
filter"player" / "players", "elite" / "elites", "mob" / "mobs", "living"(預設)
mode"full"(預設)或 "border"
coverage0.01.0 -- 取樣位置的比例(預設 1.0

監視回呼

說明
on_enterfunction(entity) -- 當實體進入區域時呼叫
on_leavefunction(entity) -- 當實體離開區域時呼叫

範例:基本球體查詢

範例
return {
api_version = 1,
on_spawn = function(context)
-- Store a zone definition for reuse
context.state.danger_zone = {
kind = "sphere",
origin = context.boss:get_location(),
radius = 10
}
end,

on_boss_damaged_by_player = function(context)
-- Update the origin to the boss's current position
context.state.danger_zone.origin = context.boss:get_location()

local players = context.zones:get_entities_in_zone(
context.state.danger_zone,
{ filter = "players" }
)

for _, player in ipairs(players) do
player:send_message("&cYou are in the danger zone!")
end
end
}

範例:帶進入/離開的區域監視

範例
return {
api_version = 1,
on_spawn = function(context)
context.zones:watch_zone(
{
kind = "sphere",
origin = context.boss:get_location(),
radius = 8
},
{
on_enter = function(entity)
entity:apply_potion_effect("SLOWNESS", 40, 1)
entity:send_message("&7You feel sluggish near the boss...")
end,
on_leave = function(entity)
entity:send_message("&aYou escape the slowing aura.")
end
},
{ filter = "players", mode = "full" }
)
end
}

觀察器注意事項:

  • 觀察器回呼直接接收單個實體包裝器,而不是透過 context.event
  • 當 Boss 被移除時,觀察器會自動清理
  • 每個觀察器每 tick 執行一次,因此保持回呼邏輯輕量
  • Boss 實體本身被排除在區域查詢之外

腳本工具:context.script

腳本工具提供目標解析、區域控制碼、相對向量、粒子生成和戰鬥動作。它們使用與 EliteScript 區域EliteScript 目標相同的欄位名稱以便於熟悉 -- 列舉名稱(如 "NEARBY_PLAYERS""SPHERE""ZONE_FULL")完全相同,這樣已經熟悉 EliteScript 的作者可以直接轉移這些知識。

資訊

context.script 是原生 Lua API。它不是通向 YAML 或 EliteScript 執行環境的橋樑。它只是重用了相同的命名慣例,這樣你就不必學習第二套列舉名稱。

方法

方法說明
script:target(spec)從目標規格表建立目標控制碼
script:zone(spec)從區域規格表建立區域控制碼
script:relative_vector(spec[, actionLocation][, zoneHandle])建立相對向量控制碼
script:damage(targetHandle, amount[, multiplier])對已解析的目標造成傷害
script:push(targetHandle, vectorOrHandle[, additive])推動已解析的目標
script:set_facing(targetHandle, vectorOrHandle)設定目標的朝向方向
script:spawn_particles(targetHandle, particleSpec)在已解析的目標位置生成粒子

目標控制碼方法

方法說明
handle:entities()傳回實體包裝器陣列
handle:locations()傳回位置表陣列
handle:first_entity()傳回第一個實體或 nil
handle:first_location()傳回第一個位置或 nil

目標規格鍵

說明
targetType"SELF", "DIRECT_TARGET", "NEARBY_PLAYERS", "NEARBY_MOBS", "NEARBY_ELITES", "ZONE_FULL", "ZONE_BORDER", "ALL_PLAYERS", "WORLD_PLAYERS", "SELF_SPAWN", "LOCATION"
range附近類型目標的範圍
coverage區域目標的 0.01.0
offset"x,y,z" 字串或 { x = n, y = n, z = n }
track是否重新解析移動的目標

範例:建立和使用目標

範例
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("roar", 200) then return end
-- Find all players within 20 blocks
local nearby = context.script:target({
targetType = "NEARBY_PLAYERS",
range = 20
})

for _, player in ipairs(nearby:entities()) do
player:send_message("&eThe boss roars in fury!")
end

-- Single-entity access
local closest = nearby:first_entity()
if closest then
closest:show_title("&cRUN!", "&7The boss is targeting you")
end
end
}

區域控制碼方法

方法說明
handle:full_target([coverage])傳回整個區域體積的目標控制碼
handle:border_target([coverage])傳回區域邊界的目標控制碼
handle:full_locations([coverage])傳回整個區域體積中的位置
handle:border_locations([coverage])傳回區域邊界上的位置
handle:full_entities()傳回整個區域體積中的實體
handle:border_entities()傳回區域邊界上的實體
handle:contains(location[, "full"|"border"])如果位置在區域內則傳回 true
handle:watch(callbacks[, mode])監視區域的進入/離開事件,傳回任務 ID

區域規格鍵

說明
shape"SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY"
radius區域半徑
height圓柱體高度
x, y, z長方體半尺寸
borderRadius邊界寬度
pointRadius射線粗細
animationDuration動畫射線的動畫長度(tick 為單位)
Target中心目標規格(表) -- 使用相同的目標規格格式
Target2射線和錐體的第二個點
filter實體篩選器
ignoresSolidBlocksboolean
pitchPreRotation, yawPreRotation預旋轉角度
pitchRotation, yawRotation每 tick 旋轉角度

範例:帶傷害和粒子的區域

範例
return {
api_version = 1,
on_enter_combat = function(context)
-- Create a sphere zone centered on the boss
local zone = context.script:zone({
shape = "SPHERE",
radius = 6,
Target = { targetType = "SELF" }
})

-- Spawn warning particles on the zone border
context.script:spawn_particles(
zone:border_target(0.3),
{ particle = "FLAME", amount = 1, speed = 0.02 }
)

-- Damage all players inside the zone
local targets = zone:full_target()
context.script:damage(targets, 5.0)

-- Repeat every 20 ticks
context.scheduler:run_every(20, function(ctx)
local z = ctx.script:zone({
shape = "SPHERE",
radius = 6,
Target = { targetType = "SELF" }
})

ctx.script:spawn_particles(
z:border_target(0.3),
{ particle = "FLAME", amount = 1, speed = 0.02 }
)

ctx.script:damage(z:full_target(), 5.0)
end)
end
}

相對向量規格鍵

說明
SourceTarget來源目標規格(表)
DestinationTarget目的地目標規格(表)
normalizeboolean -- 是否正規化結果向量
multiplier正規化後套用的縮放因子
offset"x,y,z" 字串或 { x = n, y = n, z = n }

相對向量控制碼方法

方法說明
handle:resolve()傳回計算後的向量表

範例:使用相對向量推動目標

範例
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("knockback", 100) then return end

-- Build a vector from the boss toward the attacker
local vec = context.script:relative_vector({
SourceTarget = { targetType = "SELF" },
DestinationTarget = { targetType = "DIRECT_TARGET" },
normalize = true,
multiplier = 2.5
})

-- Push the attacker away
local target = context.script:target({
targetType = "DIRECT_TARGET"
})

context.script:push(target, vec)
end
}

粒子規格格式

粒子規格可以是字串、單個表或表的陣列:

說明
particle粒子名稱(如 "FLAME""DUST""SMOKE"
amount粒子數量
x, y, z偏移/擴散值
speed粒子速度
red, green, blueDUST / DUST_COLOR_TRANSITION 的顏色(0-255)
toRed, toGreen, toBlueDUST_COLOR_TRANSITION 的過渡目標顏色

有關完整的粒子名稱列表,請參閱列舉參考

重要注意事項

  • 腳本工具控制碼繫結到建立它們的事件上下文。不要將它們儲存在 context.state 中以供後續鉤子呼叫使用。
  • 區域 watch() 傳回一個任務 ID,可以用 context.scheduler:cancel_task() 取消。
  • Coverage 值僅適用於基於位置的解析,不適用於實體查詢。
  • 所有字串值使用與 EliteScript YAML 相同的 UPPER_SNAKE_CASE 列舉名稱(如 "SELF""NEARBY_PLAYERS""SPHERE")。

em 輔助命名空間

em 命名空間在所有 Lua 能力檔案中全域可用。它提供了位置、向量和區域定義的便捷建構函式。

位置和向量建構函式

函式說明
em.create_location(x, y, z[, world][, yaw][, pitch])傳回帶有 add(dx, dy, dz) 方法的位置表
em.create_vector(x, y, z)傳回向量表

區域建構器輔助函式

em.zone 子表提供建構器函式,傳回與 context.zones 相容的區域定義表。每個建構器傳回帶有可鏈式呼叫的修改器方法的表。

函式參數修改器
em.zone.create_sphere_zone(radius)radius:set_center(location)
em.zone.create_dome_zone(radius)radius:set_center(location)
em.zone.create_cylinder_zone(radius, height)radius, height:set_center(location)
em.zone.create_cuboid_zone(x, y, z)x, y, z(半尺寸):set_center(location)
em.zone.create_cone_zone(length, radius)length, radius:set_origin(location), :set_destination(location)
em.zone.create_static_ray_zone(length, thickness)length, thickness:set_origin(location), :set_destination(location)
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration)length, point_radius, animation_duration:set_origin(location), :set_destination(location)
em.zone.create_translating_ray_zone(length, point_radius, animation_duration)length, point_radius, animation_duration:set_origin(location), :set_destination(location)

範例

範例
return {
api_version = 1,
on_spawn = function(context)
-- Create a location offset from the boss
local boss_loc = context.boss:get_location()
local above = em.create_location(boss_loc.x, boss_loc.y + 5, boss_loc.z)

-- Create a sphere zone using the builder
local zone = em.zone.create_sphere_zone(10):set_center(boss_loc)

-- Use with native zone queries
local players = context.zones:get_entities_in_zone(zone, { filter = "players" })
for _, p in ipairs(players) do
p:send_message("&cYou are within the boss's aura!")
end

-- Create a directional vector
local push_vec = em.create_vector(0, 1.5, 0)
context.boss:set_velocity_vector(push_vec)
end
}
資訊

em 命名空間不是按實例的 -- 所有 Lua 能力實例共享相同的 em 輔助函式。這些函式是純建構函式,不攜帶任何狀態。


原生區域 vs. 腳本工具

兩個系統使用相同的底層區域幾何。以下是每種方法的使用時機:

使用場景建議方法
簡單的「這個區域內有東西嗎?」檢查原生區域(context.zones
使用形狀快速查詢實體原生區域
帶 coverage 的 NEARBY_PLAYERSZONE_FULL腳本工具(context.script
動畫區域(旋轉/平移射線)都可以 -- 原生區域也支援這些形狀
watch/contains/entities 方法的區域控制碼腳本工具
在區域位置生成粒子腳本工具(spawn_particles
與目標選擇繫結的傷害和推動動作腳本工具(damagepush
方向性效果的相對向量腳本工具(relative_vector
將 Lua 控制流與豐富的目標選擇結合腳本工具

在實務中,許多能力同時使用兩者。原生區域非常適合在冷卻守衛中進行初始的「附近有玩家嗎?」檢查,而腳本工具處理隨後的複雜攻擊邏輯。


後續步驟

  • 範例與模式 -- 可供學習和改編的完整工作能力
  • API 參考 -- 完整的 context.* 方法參考
  • 列舉參考 -- Particle、Sound、Material 及其他字串常數的有效值