跳至主要內容

NPC 與首領巡邏

EliteMobs 可讓已設定的 NPC 與自訂首領使用 Minecraft 原生導航沿作者指定的路線移動。同一套系統也向 Lua 腳本提供 walk_to、hold 與 teleport。

快速編輯流程​

  1. 生成或放置要編輯的 NPC 或自訂首領。
  2. 在 12 格內直視目標並執行 /em patrol edit。
  3. 站在每個目的地執行 /em patrol add。新路線會以設定中的生成位置作為節點 0。
  4. 使用 /em patrol mode LOOP 將最後節點連回第一個節點,或使用 /em patrol mode REVERSE 按清單原路返回。
  5. 執行 /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.enabledtrue / false有節點時為 true啟用此路線。
patrol.relativetrue / falsetrue為 true 時使用相對於設定生成位置的偏移,為 false 時使用目標所在世界中的確切座標。套用於路線中的每個節點。
patrol.modeLOOP / REVERSELOOPLOOP 將最後節點連到節點 0;REVERSE 沿清單返回。
patrol.speed正有限數1.0原生導航速度倍率。
patrol.virtualSpeed正有限數移動速度屬性 × 巡邏速度持久目標沒有已載入身體時,每 tick 沿快取的已解算路徑前進的方塊數。通常應省略。
patrol.startNodeWaitSeconds0 或以上的有限數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。邏輯位置代表路線進度,可能不同於用來恢復身體的已儲存安全位置。

一般路線失敗後,巡邏控制器會重試一次,再前往下一個節點。失敗的暫時步行或停留移動也會獲得一次控制器重試,但這不代表已抵達目標。如果目標跳過節點或一直停留,請檢查地形和原生導航。