NPC 與首領巡邏
EliteMobs 可讓已設定的 NPC 與自訂首領使用 Minecraft 原生導航沿作者指定的路線移動。同一套系統也向 Lua 腳本提供 walk_to、hold 與 teleport。
快速編輯流程
- 生成或放置要編輯的 NPC 或自訂首領。
- 在 12 格內直視目標並執行
/em patrol edit。 - 站在每個目的地執行
/em patrol add。新路線會以設定中的生成位置作為節點0。 - 使用
/em patrol mode LOOP將最後節點連回第一個節點,或使用/em patrol mode REVERSE按清單原路返回。 - 執行
/em patrol save儲存路線並重新整理該實體。
編輯器顯示節點連線與已解算步行路徑的預覽。/em patrol remove 移除最後一個節點,/em patrol undo 還原先前的編輯,/em patrol status 顯示編輯驅動器的狀態。/em patrol cancel 結束工作階段而不儲存路線修改。所有編輯指令僅限玩家使用,並需要 elitemobs.patrol.admin。節點必須位於原始世界;編輯器會拒絕 WorldGuard 中 elitemob-spawning 設為 deny 的區域內的節點。
新路線使用相對座標。編輯既有路線時,編輯器會保留其 patrol.relative 設定,並以該格式儲存新增的節點。格式請在 YAML 設定中指定。
若 NPC 或區域首領檔案包含多個 spawnLocations,為其中一個目標儲存路線時,會為該地點建立子檔案,並從原檔案移除該地點。無論是相對還是絕對路線,這都能讓修改只作用於該目標。子檔案透過 extends 繼承原檔案。首領子檔案還會複製原檔案的 leashRadius、powers 與 eliteScript,因為 extends 不會繼承這些項目。
設定
巡邏節點是 x,y,z 座標。在預設的 relative: true 下,它們是相對於設定生成位置的偏移。設為 relative: false 時,它們是目標所在世界(包括其目前的副本實例世界)中的確切座標。絕對節點不包含世界名稱。
patrol:
enabled: true
relative: true
mode: LOOP
speed: 1.0
virtualSpeed: 0.2
nodes:
- 0,0,0
- 1000,0,0
- 1000,0,250
| 鍵 | 值 | 預設值 | 說明 |
|---|---|---|---|
patrol.enabled | true / false | 有節點時為 true | 啟用此路線。 |
patrol.relative | true / false | true | 為 true 時使用相對於設定生成位置的偏移,為 false 時使用目標所在世界中的確切座標。套用於路線中的每個節點。 |
patrol.mode | LOOP / REVERSE | LOOP | LOOP 將最後節點連到節點 0;REVERSE 沿清單返回。 |
patrol.speed | 正有限數 | 1.0 | 原生導航速度倍率。 |
patrol.virtualSpeed | 正有限數 | 移動速度屬性 × 巡邏速度 | 持久目標沒有已載入身體時,每 tick 沿快取的已解算路徑前進的方塊數。通常應省略。 |
patrol.startNodeWaitSeconds | 0 或以上的有限數 | 0 | 目標每次回到節點 0 時停留的秒數:LOOP 每繞一圈一次,REVERSE 每趟來回一次。在節點 0 生成的目標,在第一圈開始前也會停留。停留期間會面向其生成時的朝向。 |
patrol.nodes | 至少兩個座標 | 無 | 依序排列的目的地,依 patrol.relative 解讀。支援 x,y,z 字串或包含 x、y、z 的映射。座標必須有限,相鄰節點不能相同。 |
例如,以下路線會依序前往三個確切位置,再循環回到第一個位置:
patrol:
enabled: true
relative: false
mode: LOOP
nodes:
- 299,91,215
- 286,91,213
- 279,91,230
沒有 patrol.relative 的既有路線會繼續使用偏移。變更此旗標會改變每個節點的解讀方式,但不會轉換已儲存的數值。變更既有路線的格式時,請一併轉換節點。
系統沒有公開的單段距離上限,1,000 格的路段也是有效的。舊實驗鍵 patrol.maxLegDistance 已淘汰且不起作用。
儲存時,編輯器會保留路線的導航速度、明確設定的 virtualSpeed 以及起始節點停留設定。解析超過兩個節點的路線時,若最後一個節點重複了首節點,會自動移除該末尾節點。
NPC 接近玩家時暫停
NPC 也支援 patrol.pauseNearPlayersRadius(預設 0,停用)與 patrol.faceNearbyPlayers(預設 false)。設定正有限半徑後,NPC 會在接近存活且非旁觀模式的玩家時暫停;朝向選項讓暫停的 NPC 看向最近的有效玩家。距離每 20 tick 檢查一次。無效或負半徑會停用這種暫停。
這些選項獨立於對話和 Lua 手動巡邏暫停。它們是 NPC 選項,不是首領巡邏的額外欄位。
起始節點停留
設定 patrol.startNodeWaitSeconds 後,目標會在開始下一圈之前停在節點 0。目標未載入時,停留時間也會持續倒數。接近玩家或戰鬥造成的暫停會讓倒數停止,直到暫停結束。walk_to、hold、teleport 與 patrol_resume() 會立即結束停留。公會的戰鬥教官使用 60 秒的停留時間,讓玩家能在他兩圈之間於椅子旁找到他。
長距離尋路
長路段會自動解算。EliteMobs 讓 MagmaCore 在目前已載入地形中滾動規劃路線,將它拆成原生導航可處理的短目標,並隨實體前進持續重新規劃。
地形存取與路線搜尋分開處理:
- 已載入區塊的快照透過 MagmaCore 共用的 tick 預算工作負載系統,在伺服器執行緒中擷取。
- 有界 A* 搜尋在這些不可變快照上非同步執行。
- 最終短路段仍由 Minecraft 原生尋路器驗證並行走。
- 規劃不會強制載入區塊。缺少地形時會等待並重試。沒有身體的持久目標只能沿快取的已解算路徑前進,路徑用盡後等待。其身體只能在進行實體 tick 的區域恢復。
這樣便能穿越整座城市,而無須在單一 tick 內掃描所有地形,也不會沿直線穿過未載入的建築。飛行與水生生物使用體積搜尋;地面生物要求有支撐與足夠空間,並避開常見危險方塊。
實體行為
- NPC 巡邏會自動啟用身體 AI 與自訂模型移動同步。
syncMovement仍控制不巡邏的模型,但它不是第二個巡邏開關。 - 自訂首領必須使用
ai: true、具有正的移動速度,且不能是其他實體的乘客。 - 首領進入戰鬥時暫停巡邏,戰鬥結束後恢復。
- 非實例化的 NPC 與非實例化的持久首領會在區塊卸載與重載期間,將安全路線位置儲存在
patrol-state.yml。當路線的節點或relative旗標變更時,已儲存的位置會被捨棄,目標會從節點0重新開始。 - 目標只會在進行實體 tick 的區域恢復身體。沒有身體時,儲存的位置仍可沿先前已解算的路徑前進,但不會在未知地形中尋找新路線。
- 乘客不能擁有巡邏路線;請為其坐騎設定路線。
Lua 控制
context.npc 與 context.boss 提供以下方法,其巡邏操作需要已設定的控制器。無論 patrol.relative 為何,Lua 座標一律是相對於原始生成位置的偏移,各方法回傳請求是否被接受。walk_to、hold 與 teleport 也需要存活的身體。步行請求被接受不代表已抵達:戰鬥、接近玩家時的暫停、關閉 AI 或尋路失敗都可能中斷移動。
| 方法 | 行為 |
|---|---|
patrol_pause() | 停止目前路線但保留設定。 |
patrol_resume() | 取消腳本等待或暫時移動並恢復巡邏。 |
walk_to(x, y, z) | 走到偏移位置,然後恢復巡邏。 |
hold(x, y, z) | 走到偏移位置並停留,直到呼叫 patrol_resume()。 |
teleport(x, y, z) | 當同一世界內的目標區域進行實體 tick 且 Bukkit 接受傳送時,將存活的身體傳送到偏移位置。不會清除既有的腳本暫停或暫時目標;使用 patrol_resume() 返回路線。 |
return {
api_version = 1,
on_npc_interact = function(context)
context.npc:walk_to(40, 0, -12)
end
}
walk_to 使用相同的長距離解算器,無須手動拆分中繼節點。
診斷
在編輯工作階段之外,直視目標並執行 /em patrol status。輸出包含執行狀態、目前與目標節點、路線進度、邏輯位置、虛擬速度、身體是否存在及暫停原因。start_node_wait 表示正在起始節點停留。terrain_unavailable 表示無身體移動已沒有可用的已解算路徑;已載入目標等待規劃時可能顯示 yielded。邏輯位置代表路線進度,可能不同於用來恢復身體的已儲存安全位置。
一般路線失敗後,巡邏控制器會重試一次,再前往下一個節點。失敗的暫時步行或停留移動也會獲得一次控制器重試,但這不代表已抵達目標。如果目標跳過節點或一直停留,請檢查地形和原生導航。