Lua-Scripting: NPC-Scripts
EliteMobs-NPC-Lua-Scripts sind eigenständige .lua-Dateien, die an NPC-Konfigurationen angehängt werden. Sie sind von den Boss-Lua-Powers getrennt: Boss-Powers liegen in plugins/EliteMobs/powers/, während NPC-Scripts in plugins/EliteMobs/npc_scripts/ liegen.
NPC-Scripts verwenden die gemeinsame MagmaCore-Laufzeit wie Boss-Powers und FreeMinecraftModels-Props. Sie erhalten context.world, context.zones, context.scheduler, context.cooldowns und context.log sowie eine NPC-spezifische Tabelle context.npc. Spieler- und Ereignisdaten hängen vom Hook ab. Boss-Powers besitzen eigene Varianten mehrerer Tabellen; verwende für NPC-Scripts die gemeinsamen API-Signaturen.
NPC-Lua-Scripts sind noch experimentell. Die NPC-spezifischen Hooks und die context.npc-Helfer können sich ändern. Die gemeinsamen Tabellen (context.world, context.zones, context.scheduler, context.cooldowns, context.log, context.event, context.player) sind dieselben, die in der Scripting-Engine und der Lua-API-Referenz dokumentiert sind.
Dateispeicherort
Erstelle NPC-Script-Dateien in:
plugins/
EliteMobs/
npc_scripts/
wave.lua
Unterordner werden rekursiv durchsucht. Scripts werden jedoch nur anhand des Dateinamens registriert, sodass npc_scripts/wave.lua und npc_scripts/town/wave.lua kollidieren -- halte die Basisnamen im gesamten Verzeichnisbaum eindeutig.
Die Suche wählt pro Basisname ohne Beachtung der Großschreibung eine Datei in stabiler absoluter Pfadreihenfolge. Unterscheiden sich die Kopien, werden ausgewählte und übersprungene Pfade protokolliert. Ist die ausgewählte Datei defekt, wird kein übersprungenes Duplikat als Ersatz geladen. Konfigurationsverweise müssen weiterhin die genaue Großschreibung der ausgewählten Datei verwenden.
Die Endung .lua ist in einer NPC-Konfiguration optional: - wave und - wave.lua werden beide zu wave.lua aufgelöst. Verweist eine NPC-Konfiguration auf ein Script, das nicht existiert, protokolliert EliteMobs eine Warnung und der NPC spawnt trotzdem.
Scripts an NPCs anhängen
Füge der NPC-Konfiguration eine scripts:-Liste hinzu:
scripts:
- wave.lua
An einen NPC können mehrere Scripts angehängt werden:
scripts:
- wave.lua
- greeting_particles.lua
Scripts laufen nach aufsteigender Priorität. priority ist standardmäßig 0. Gleiche Prioritäten behalten die Reihenfolge in scripts: bei. Dies ordnet NPC-Ereignisse, nicht unabhängige geplante Tasks.
Script-Aufbau
Jedes NPC-Script muss genau eine Tabelle zurückgeben:
return {
api_version = 1,
priority = 0,
on_spawn = function(context)
context.state.spawned = true
context.npc:play_model_animation("idle")
end
}
Nur diese Top-Level-Felder werden akzeptiert:
| Feld | Typ | Hinweise |
|---|---|---|
api_version | number | Erforderlich. Muss 1 sein. |
priority | number | Optional. Niedrigere Werte laufen zuerst. |
on_spawn | function | Läuft, nachdem der NPC gespawnt ist. |
on_remove | function | Läuft während der normalen NPC-Entfernung, vor Script-Shutdown und Entfernung des Körpers. |
on_game_tick | function | Läuft jeden Server-Tick, sobald die Script-Laufzeit initialisiert und ihre Clock aktiv ist. Halte die Arbeit gering. |
on_npc_interact | function | Läuft, wenn die normale Interaktionsverarbeitung den Script-Schritt erreicht; siehe die Einschränkungen unten. |
on_npc_proximity_enter | function | Läuft einmal, wenn ein Spieler den Aktivierungsradius dieses NPCs betritt. |
on_npc_proximity_leave | function | Läuft einmal, wenn ein Spieler den Aktivierungsradius dieses NPCs verlässt. |
on_zone_enter | function | Läuft, wenn ein Spieler eine Zone betritt, die dieses Script überwacht (siehe context.zones). |
on_zone_leave | function | Läuft, wenn ein Spieler eine überwachte Zone verlässt. |
Die Zonenüberwachung verfolgt nur Spieler -- Mobs und andere Entities lösen on_zone_enter / on_zone_leave niemals aus.
Unbekannte Top-Level-Schlüssel werden beim Laden des Scripts abgelehnt. Hilfsfunktionen sollten als local-Funktionen oberhalb der zurückgegebenen Tabelle deklariert werden.
Der Loader führt Code auf Dateiebene zur Validierung aus. Jede NPC-Script-Instanz führt ihn später erneut in ihrer eigenen Sandbox aus. Verwende bei der Dateiinitialisierung keinen Hook-Kontext. Jedes Script besitzt eigene Globals und context.state, auch auf demselben NPC.
NPC-Laufzeiten werden verzögert initialisiert. Der NPC erstellt derzeit jede Instanz und sendet on_spawn, ruft aber nicht die sofort initialisierende Methode start() auf. Eine Datei mit ausschließlich on_game_tick beginnt daher nicht selbständig zu ticken. Definiere on_spawn = function(context) end, um sie beim Spawn zu initialisieren, oder lass einen anderen deklarierten Ereignis-Hook später die Initialisierung auslösen.
Ein Lua-Fehler schließt die betroffene Instanz und bricht ihre eigene Arbeit ab. Spätere NPC-Ereignisse entfernen geschlossene Instanzen, ohne sie neu zu erstellen. Lade die korrigierte Definition neu und erstelle eine neue NPC-Script-Instanz. Zustand wird nicht über Entfernung oder Neustart hinweg gespeichert. on_remove ist ein NPC-Entfernungs-Hook, kein allgemeiner Fehler- oder Shutdown-Callback.
Näherungs-Hooks
Die NPC-Näherungs-Hooks verwenden den Konfigurationswert activationRadius des NPCs.
| Hook | Wird ausgelöst, wenn |
|---|---|
on_npc_proximity_enter | Ein Spieler sich von außerhalb des Aktivierungsradius des NPCs nach innen bewegt. |
on_npc_proximity_leave | Ein Spieler sich von innerhalb des Aktivierungsradius des NPCs nach außen bewegt. |
Der serverseitige Scanner prüft jedes NPC-Spieler-Paar alle 100 Ticks, bei 20 TPS normalerweise alle fünf Sekunden. Er verwendet die kugelförmige Entfernung vom aktuellen NPC-Körper. Ein bereits beim ersten Scan anwesender Spieler zählt als Eintritt. Ein kurzer Besuch zwischen zwei Scans kann unbemerkt bleiben. Die Nähe zu einem NPC blockiert den Eintritt bei einem anderen nicht; fortgesetzte Erkennung im Radius wiederholt das Ereignis nicht.
Aktiv patrouillierende NPCs und NPCs im Editor werden übersprungen. Ein zuvor erkanntes Paar kann deshalb beim Bewegungsbeginn ein Austrittsereignis und bei erneuter Erkennung einen Eintritt auslösen. Entfernung und Logout garantieren keinen Austritts-Hook: Dafür müssen der registrierte NPC und ein Spieler online vorhanden sein. Gibt es keine NPCs oder keine Online-Spieler, wird die Erkennung ohne Austrittsereignisse geleert. activationRadius kleiner oder gleich null deaktiviert die Näheaktivierung. Die getrennte 30-Block-Reichweite von Quest-Markierungen erweitert die Lua-Aktivierung nicht.
Das normale Verhalten für Begrüßung, Dialog und Quest-Indikator läuft weiterhin. Der Lua-Hook fügt zusätzliches Verhalten hinzu.
Gemeinsame Scripting-API
Da NPC-Scripts auf der vereinheitlichten Laufzeitumgebung laufen, erhält jeder NPC-Hook auch die gemeinsamen MagmaCore-Context-Tabellen, die von FreeMinecraftModels-Scripts verwendet werden. EliteMobs-Boss-Powers laufen auf derselben Laufzeitumgebung, verwenden aber für mehrere Tabellen boss-spezifische Varianten. Vollständige Methodenlisten findest du in der Lua-API-Referenz und der Scripting-Engine:
| Tabelle | Wofür sie da ist |
|---|---|
context.world | Welteffekte und -abfragen: strike_lightning, spawn_particle, play_sound, set_block_at, place_temporary_block, spawn_entity, spawn_firework, get_nearby_entities, get_nearby_players, raycast und mehr. Sowohl die Koordinatenform (strike_lightning(x, y, z)) als auch die Location-Tabellen-Form (strike_lightning_at_location(loc)) werden akzeptiert. |
context.zones | Erstellt Zonen mit create_sphere(x, y, z, radius), create_cylinder(x, y, z, radius, height) oder create_cuboid(x, y, z, xSize, ySize, zSize). Gibt einen numerischen Handle zurück, ohne Besitzerwelt nil. watch(handle, on_enter, on_leave) aktiviert die entsprechenden Top-Level-Hooks, wenn ein Funktionsargument vorliegt; die übergebene Funktion selbst wird nicht aufgerufen. unwatch(handle) entfernt die Zone und beendet die Verfolgung. |
context.scheduler | run_later(ticks, fn), run_repeating(delay, interval, fn), cancel(task_id). |
context.cooldowns | Gemeinsame MagmaCore-Abklingzeiten: local_ready, local_remaining, check_local, set_local, global_ready, set_global. |
context.log | info(msg), warn(msg), error(msg) — schreibt in die Serverkonsole. |
context.event | Ereignis- oder Akteursdaten, wenn der Hook solche liefert. Siehe unten. |
context.player | Der interagierende/auslösende Spieler, sofern vorhanden. Siehe unten. |
context.state | Eine einfache Lua-Tabelle, die für diese NPC-Script-Instanz bestehen bleibt, bis der NPC entfernt wird. |
Gemeinsame Zonen verwenden absolute Koordinaten in der NPC-Welt zum Erstellungszeitpunkt und folgen keinem bewegten NPC. Schon das Erstellen registriert einen Scan der Spieler in der aktuellen Besitzerwelt für jeden Tick, bevor watch Eintritts- und Austrittsbehandlung installiert. Übergib für jede gewünschte Richtung eine Funktion und implementiere den passenden Hook on_zone_enter oder on_zone_leave in der Rückgabetabelle. Diese Hooks erhalten context.player und eine Akteursereignistabelle, aber keine Zonenkennung. unwatch entfernt den Handle vollständig; erstelle zum erneuten Überwachen eine neue Zone. Beim ersten Scan bereits anwesende Spieler zählen als Eintritte; Offline-Spieler erhalten keinen Austritts-Callback.
Beispiel: Blitzschlag bei Interaktion
return {
api_version = 1,
on_npc_interact = function(context)
-- NPC scripts can now reach the full world API.
context.world:strike_lightning_at_location(context.npc:get_location())
end
}
context.npc
context.npc ist in jedem NPC-Hook verfügbar.
Felder
| Feld | Typ | Hinweise |
|---|---|---|
name | string | NPC-Anzeigename aus der Konfiguration. |
filename | string | Dateiname der NPC-Konfiguration. |
uuid | string | Laufzeit-UUID des NPCs. |
activation_radius | number | Konfigurierter Aktivierungsradius. |
current_location | location table | Momentaufnahme der Position, wenn die zugrunde liegende Entity existiert. |
entity_type | string | Bukkit-Entity-Typ, wenn die zugrunde liegende Entity existiert. |
Methoden
| Methode | Argumente | Rückgabe | Hinweise |
|---|---|---|---|
is_valid() | - | boolean | Ob der NPC noch eine gültige zugrunde liegende Entity hat. |
get_location() | - | location table | Aktuelle NPC-Position oder Spawn-Position, wenn die Entity nicht verfügbar ist. |
get_eye_location() | - | location table | Aktuelle Augenposition oder Rückfall auf die Spawn-Position. |
get_activation_radius() | - | number | Aktuell konfigurierter Aktivierungsradius. |
get_nearby_players(radius) | number | table | Spieler-Wrapper innerhalb der kugelförmigen Entfernung in der NPC-Welt. Kein Spielmodusfilter; verwende einen nichtnegativen Radius. |
face_direction_or_location(target) | Vektor, Position oder Entitätstabelle | nil | Blickt in eine Richtung oder zu einer Position derselben Welt. Tabellen mit world oder current_location gelten als Position, bloße Koordinaten als Richtung. Während aktiver Patrouillenbewegung ohne Wirkung. |
say_greeting(player?) | player, UUID, Name oder nil | nil | Sendet eine konfigurierte Begrüßung. Standardmäßig an den auslösenden Spieler, sofern verfügbar. |
say_dialog(player?) | player, UUID, Name oder nil | nil | Sendet konfigurierten Dialog. Standardmäßig an den auslösenden Spieler, sofern verfügbar. |
say_farewell(player?) | player, UUID, Name oder nil | nil | Sendet konfigurierten Abschiedstext. Standardmäßig an den auslösenden Spieler, sofern verfügbar. |
play_model_animation(name) | string | nil | Spielt eine benutzerdefinierte Modellanimation ab, sofern vorhanden. Andernfalls ein gefahrloser No-Op. |
patrol_pause() | - | boolean | Pausiert die konfigurierte Patrouille. |
patrol_resume() | - | boolean | Beendet einen Skript-Halt oder temporären Lauf und setzt die Patrouille fort. |
walk_to(x, y, z) | drei Zahlen | boolean | Läuft zu einem Versatz vom konfigurierten Spawn und setzt danach die Patrouille fort. Lange Wege werden automatisch gelöst. |
hold(x, y, z) | drei Zahlen | boolean | Läuft zu einem Versatz vom konfigurierten Ursprung und bleibt dort. |
teleport(x, y, z) | drei Zahlen | boolean | Teleportiert zu einem Versatz vom konfigurierten Ursprung, wenn am Ziel Entitäten ticken. |
remove() | - | nil | Entfernt den aktuellen Körper über den normalen Ablauf mit Grund OTHER; löscht nicht den konfigurierten Standort. Nicht aus on_remove aufrufen, da dies die Entfernung erneut auslösen würde. |
Bewegungsmethoden geben false zurück, wenn der NPC keine konfigurierte Patrouille besitzt oder die Anfrage nicht angenommen werden kann. Siehe NPC- und Boss-Patrouillen.
context.player
context.player ist in on_npc_interact, on_npc_proximity_enter, on_npc_proximity_leave sowie den Eintritts- und Austritts-Hooks überwachter Zonen verfügbar. In Lebenszyklus-Hooks ohne Spieler ist es nil.
Es handelt sich um den gemeinsamen MagmaCore-Spieler-Wrapper, den auch FMM verwendet. Er bietet Gesundheit, Trankeffekte, send_message, show_title, show_action_bar, get_held_item, Raycasting und weitere Methoden. Boss-Powers besitzen einen eigenen Wrapper; ihre Methoden sind nicht austauschbar. Die vollständige Liste steht in der Lua-API-Referenz. Häufige Mitglieder sind:
| Feld / Methode | Hinweise |
|---|---|
name | Spielername. |
uuid | Spieler-UUID. |
current_location | Bei jedem Feldzugriff live gelesene Spielerposition. Eine zuvor gespeicherte Positionstabelle bleibt eine Momentaufnahme. |
get_eye_location() | Aktuelle Augenposition des Spielers. |
send_message(text) | Sendet eine Chatnachricht. Unterstützt Farbcodes. |
Prüfe context.player immer auf nil, bevor du es in gemeinsamen Hilfsfunktionen verwendest.
entity_type ist hier kleingeschriebenBei gemeinsamen MagmaCore-Entitätstabellen ist entity_type der Bukkit-Name in Kleinbuchstaben ("player", "zombie"). Nur context.npc.entity_type und die Entitätstabellen von EliteMobs-Boss-Powers verwenden die Großschreibung. Vergleiche ohne Beachtung der Groß-/Kleinschreibung, wenn ein Script mit beidem umgehen muss.
EliteMobs-Felder, die jeder gemeinsamen Entitätstabelle hinzugefügt werden
Während EliteMobs läuft, ergänzt es gemeinsame MagmaCore-Entitätstabellen, darunter context.player, die Wrapper von context.npc:get_nearby_players(...) und FreeMinecraftModels-Prop-Scripts:
| Feld / Methode | Typ | Hinweise |
|---|---|---|
is_elite | boolean | true, wenn EliteMobs die Entität als Elite verfolgt |
is_custom_boss | boolean | true, wenn es sich um einen Custom Boss handelt (immer false, wenn is_elite false ist) |
is_significant_boss | boolean | true bei einem Custom Boss mit Gesundheitsmultiplikator über 1. Prüft nicht, ob er als Verstärkung beschworen wurde. |
elite | Tabelle oder nil | Nur bei Elites vorhanden. Siehe unten |
elite_player | Tabelle oder nil | Auf gemeinsamen Spieler-Wrappern aus EliteMobs ist tier verfügbar, wenn das Elite-Inventar geladen ist. Jeder Feldzugriff erzeugt eine neue Tabelle; eine gespeicherte Tabelle behält ihren alten Tier-Wert. |
can_receive_hostile_effect(actor_uuid) | boolean | Prüft einen Spielerakteur anhand gemeinsamer Regeln für feindliche Ziele und der EliteMobs-Autorisierung für magische Waffen. Gültigen UUID-String übergeben. |
Die elite-Untertabelle:
| Feld / Methode | Typ | Hinweise |
|---|---|---|
elite.level | number | Elite-Level |
elite.name | string oder nil | Anzeigename des Elites |
elite.health | number | Aktuelle Gesundheit des Elites (live gelesen) |
elite.max_health | number | Maximale Gesundheit des Elites (live gelesen) |
elite.is_custom_boss | boolean | Derselbe Wert wie das Feld auf oberster Ebene |
elite.health_multiplier | number | Konfigurierter Gesundheitsmultiplikator |
elite.damage_multiplier | number | Konfigurierter Schadensmultiplikator |
elite:remove() | — | Despawnt den Elite |
-- Warn the approaching player if a real boss is loose near this NPC
on_npc_proximity_enter = function(context)
if context.player == nil then return end
local here = context.npc:get_location()
local nearby = context.world:get_nearby_entities(here.x, here.y, here.z, 40)
for i = 1, #nearby do
if nearby[i].is_significant_boss then
context.player:send_message("&cA boss is nearby: " .. tostring(nearby[i].elite.name))
return
end
end
end
Boss-Power-Wrapper verwenden einen getrennten Builder mit anderen Feldern. Einige Namen wie is_elite überschneiden sich; die gemeinsame Untertabelle elite ist jedoch nicht mit Boss-Power-Methoden austauschbar. Siehe Bosse & Entitäten. FMM besitzt einen eigenen EliteMobs-Adapter. Gehe nicht davon aus, dass jedes zusätzliche Feld eines EliteMobs-gebauten Wrappers auch in FMM existiert.
context.event
context.event ist nur dann nil, wenn der Hook weder Ereignis noch Akteur hat. Es ist die gemeinsame MagmaCore-Ereignistabelle:
| Feld / Methode | Hinweise |
|---|---|
is_cancelled | Momentaufnahme des Abbruchstatus beim Erstellen der Tabelle; bei nicht abbrechbaren Ereignissen false. Ändert sich nach cancel() oder uncancel() nicht. |
cancel() | Nur bei abbrechbarem Ereignis vorhanden. Bricht dieses Ereignis ab. |
uncancel() | Nur bei abbrechbarem Ereignis vorhanden. Hebt dessen Abbruch auf. |
player | Der Akteur des Events (z. B. der interagierende Spieler) als Spieler-Wrapper, sofern vorhanden. |
Für den interagierenden Spieler bzw. den Näherungs-Spieler ist context.player vorzuziehen (es ist für diese Hooks gesetzt).
on_npc_interact liefert derzeit den Spieler ohne Bukkit-Ereignis. Seine Tabelle enthält daher player und is_cancelled: false, aber weder cancel noch uncancel. Ein Script kann das normale NPC-Menü nicht über diese Tabelle abbrechen.
Der Interaktionspfad ignoriert bereits abgebrochene Bukkit-Interaktionen, blockiert Namensschilder und NPCs im Editor und begrenzt Interaktionen pro Spieler auf eine je Tick. Verbraucht ein Quest-Dialogziel die Interaktion, endet der Aufruf vor dem Lua-Hook. Andernfalls läuft der Hook vor der normalen Menü- oder Aktionsverarbeitung. Näherungsereignisse sind ebenfalls nicht abbrechbar; Zonen-Hooks liefern einen Akteur ohne Bukkit-Ereignis. Auch diese Pfade bieten weder cancel() noch uncancel().
State, Scheduler und Abklingzeiten
context.state gehört dieser einzelnen NPC-Script-Instanz und besteht bis zu ihrem Ende. Es ist vom Zustand anderer Scripts desselben NPCs getrennt.
context.scheduler ist der gemeinsame MagmaCore-Scheduler. Sowohl die MagmaCore-Namen als auch die EliteMobs-Namen run_after / run_every funktionieren — sie sind Aliase für dasselbe Verhalten:
| Methode | Argumente | Hinweise |
|---|---|---|
run_later(ticks, callback) / run_after(ticks, callback) | number, function | Läuft einmal nach einer Verzögerung. Gibt eine Task-ID zurück. |
run_repeating(delay, interval, callback) | number, number, function | Läuft nach einer anfänglichen Verzögerung wiederholt. Gibt eine Task-ID zurück. |
run_every(interval, callback) | number, function | Läuft alle interval Ticks (anfängliche Verzögerung 0). Gibt eine Task-ID zurück. |
cancel(task_id) / cancel_task(task_id) | number | Bricht einen eigenen Task ab. |
Scheduler-Callbacks erhalten einen frischen Context. Sie erhalten nicht das ursprüngliche context.player oder context.event. Alle eigenen Tasks werden automatisch abgebrochen, wenn der NPC entfernt wird.
context.cooldowns ist die gemeinsame MagmaCore-Abklingzeit-Tabelle:
| Methode | Argumente | Rückgabe | Hinweise |
|---|---|---|---|
local_ready(key?) | string | boolean | True, wenn die lokale Abklingzeit abgelaufen ist. |
local_remaining(key?) | string | number | Verbleibende Ticks oder 0, wenn bereit. |
check_local(key?, duration) | string, number | boolean | Startet die Abklingzeit, wenn bereit, und gibt true zurück. |
set_local(duration, key?) | number, string | nil | Setzt die Abklingzeit oder setzt sie zurück. |
global_ready() | - | boolean | True, wenn die gemeinsame globale Abklingzeit bereit ist. |
set_global(duration) | number | nil | Startet die globale Abklingzeit. |
Bei check_local steht die Dauer immer an zweiter Stelle: Verwende check_local(nil, 60) für den Standardschlüssel. set_local erwartet dagegen zuerst die Dauer. Der Standardschlüssel enthält den Script-Dateinamen. Explizite lokale Schlüssel und der globale Cooldown-Speicher werden zwischen Scripts desselben NPC-Adapters geteilt. Verwende unterschiedliche Schlüssel, sofern keine Koordination beabsichtigt ist. Die Dauer verwendet monotone verstrichene Zeit mit 50 ms pro nominellem Tick, nicht gezählte Server-Ticks. Nichtpositive Dauern löschen die Abklingzeit. Ein globaler Cooldown blockiert weder Hooks noch check_local automatisch; prüfe global_ready() selbst.
NPC-Scripts verwenden jetzt die gemeinsame MagmaCore-Abklingzeit-Reihenfolge (check_local(key?, duration)), genau wie Boss-Powers und FreeMinecraftModels-Scripts. Frühere experimentelle NPC-Builds verwendeten check_local(duration, key?) — aktualisiere alte Scripts auf die gemeinsame Reihenfolge.
Beispiel: Winken bei Annäherung
Dieses Script richtet den NPC auf einen erkannten eintretenden Spieler aus und spielt wave. Die Eintrittserkennung beruht auf dem Fünf-Sekunden-Scan, nicht auf jedem Bewegungspaket. Der Cooldown mit eigenem Schlüssel begrenzt Wiederholungen bei mehrfachen Eintrittsmeldungen; er erhöht die Scanner-Frequenz nicht.
return {
api_version = 1,
priority = 0,
on_npc_proximity_enter = function(context)
if context.player == nil then return end
if context.cooldowns:check_local("wave:" .. context.player.uuid, 60) then
context.npc:face_direction_or_location(context.player.current_location)
context.npc:play_model_animation("wave")
end
end
}
play_model_animation(name) tut gefahrlos nichts, wenn der NPC kein benutzerdefiniertes Modell hat oder das Modell diese Animation nicht besitzt.
Performance-Richtlinien
- Halte
on_game_tick-Hooks klein. Nach der Initialisierung läuft ihre Clock jeden Server-Tick, normalerweise 20-mal pro Sekunde. Ein Script ohne diesen Hook kann weiterhin Zonen pro Tick prüfen oder explizite geplante Arbeit ausführen. - Bevorzuge
on_npc_proximity_enterundon_npc_proximity_leavefür Näherungsverhalten, statt in jedem Tick nahe Spieler abzufragen. - Verwende
context.cooldowns:check_local(...), um Animationen, Sounds und Partikelausbrüche zu drosseln. - Verwende
context.scheduler:run_repeating(...)mit einem sinnvollen Intervall, wenn ein Verhalten nicht in jedem Tick laufen muss. - Vermeide große Suchvorgänge in Lua.
context.npc:get_nearby_players(radius)ist für kleine lokale Prüfungen in Ordnung, aber breites Scannen sollte in der Plugin-Laufzeitumgebung bleiben.
Verwandte Seiten
- NPCs erstellen -- NPC-Konfigurationsfelder, einschließlich
activationRadius - Lua: Erste Schritte -- Boss-Lua-Powers
- Scripting-Engine -- gemeinsame Lua-Konzepte und die vereinheitlichte Laufzeitumgebung
- Lua-API-Referenz -- vollständige Methodenliste für
context.world,context.player,context.zonesund mehr
