Repository navigation
UO Topic scripts runtime
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
Головна · C# · IDE · Команди UO · За абеткою · Приклади · Мови
Запуск, пауза та зупинка скриптів, виклик зареєстрованих функцій, події й очікування. Terminate зупиняє відповідну функцію, а StopScript — запуск скрипта; параметри та межі дії наведено в їхніх описах.
| Тема | Команди та пояснення |
|---|---|
| Запуск скрипта | UO.StartScript |
| Зупинка скрипта | UO.StopScript |
| Зупинка всіх скриптів | UO.StopAllScripts |
| Пауза та продовження | UO.PauseResumeScript |
| Стан скрипта | UO.GetScriptState |
| Список скриптів | UO.GetScriptsList · UO.GetScriptsCount |
| Назва скрипта | UO.GetScriptName · UO.SetScriptName |
| Шлях до скрипта | UO.GetScriptPath |
| Виклик зареєстрованої функції | UO.CallSub |
| Перевірка наявності функції | UO.SubExists |
| Події | UO.SetEvent · UO.SetEventProc |
| Таймери | UO.Timer · UO.Wait |
| Поведінка після відключення | UO.GetPauseScriptOnDisconnectStatus · UO.SetPauseScriptOnDisconnectStatus |
UO.StartScript · UO.StopScript · UO.StopAllScripts · UO.PauseResumeScript · UO.GetScriptName · UO.SetScriptName · UO.GetScriptPath · UO.GetScriptsCount · UO.GetScriptsList · UO.GetScriptState · UO.Exec · UO.Launch
UO.CallSub · UO.SubExists · UO.FunRunning · UO.Terminate · UO.TerminateAll · UO.SetEvent · UO.SetEventProc
UO.Wait · UO.Waiting · UO.Timer · UO.Time · UO.Date
UO.GetPauseScriptOnDisconnectStatus · UO.SetPauseScriptOnDisconnectStatus
Нижче наведено короткі приклади. У повному описі кожної команди є параметри, результат, обмеження та кілька самостійних скриптів: прямий код, варіант із функцією та варіант із класом.
Параметри, результат та всі сценарії
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
UO.Print(Convert.ToString(index) + ": " + UO.GetScriptName(index));
}Параметри, результат та всі сценарії
for (int cycle = (int)(1); cycle <= 10; cycle += (int)(1))
{
if (Truth(UO.Dead()))
{
UO.Print("Character is dead: stopping all C# scripts");
UO.TerminateAll();
}
await Delay(250);
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.CallSub(object? subrutineName);Запускає C#-делегат, заздалегідь зареєстрований у поточному виконанні через RegisterRoutine(name, handler). Виклик повертає керування до завершення помічника; одне зареєстроване завдання не можна накладати на себе.
-
subrutineName— рядкове ім’я, задане RegisterRoutine. Пробіли по краях видаляються; пошук зареєстрованого імені не залежить від регістру.
void - результату немає; невідоме ім'я CallSub викликає помилку, а повторний запуск активного імені вже пропускається.
Значення UO.FunRunning(name) == 0 також можливе одразу після запиту скасування. Воно не означає, що блок finally попереднього callback уже завершився. Повторний CallSub або Exec того самого локального імені пропускається, поки попередній обробник фактично не завершить роботу.
- Реєстрація та завдання належать одному виконанню. Інший персонаж, профіль чи наступний запуск має власний реєстр.
- ?RegisterRoutine? приймає ?
Action?, ?Func<Task>? або делегат з масивом рядкових аргументів для ?Exec?. Видалення реєстрації не запускає код і унеможливлює подальший пошук імені. - Основний скрипт повинен залишатися активним, поки потрібні його помічники: після закінчення завдання скасовуються, а реєстрації та підписки звільняються.
- FunRunning не є індексом менеджера. GetScriptsList та GetScriptState описують самостійні запуски файлів; локальний callback окремого індексу не отримує.
- Помилка callback передається основному скрипту на наступній перевірці. WaitAsync, UO.Wait та інструментовані C#-цикли підтримують паузу, скасування та обробку черги подій.
Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
RegisterRoutine("Hello", () => UO.Print("Hello from a routine"));
UO.CallSub("Hello");
while (UO.FunRunning("Hello") != 0) await WaitAsync(25);Параметри та порядок виконання:
- WeightWatch - ім'я процедури нижче. Main повертає 77, не чекаючи трьох вимірів; 77 — результат Main, не CallSub.
- Збережіть приклад як окремий файл, завантажте його в IDE/менеджер і запускайте Main, щоб інші процедури потрапили до каталогу. WeightWatch/ManaWatch — повністю визначені тут навчальні процедури: три виміри ваги/мани з інтервалом UO.Wait(1000), тобто 1000 мс, висновок лише при вході у світ. Це не постійний моніторинг; пауза може розтягнути час. Для прикладу із двома завданнями має бути дозволено одночасний запуск процедур.
var registrationWeightWatch = RegisterRoutine("WeightWatch", WeightWatch);
UO.CallSub("WeightWatch");
while (UO.FunRunning("WeightWatch") != 0) await WaitAsync(25);
return 77;
void WeightWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Weight: " + Convert.ToString(UO.Weight()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- StartIfIdle спочатку перевіряє визначення, потім активність. false означає, що запит не надіслано. true означає лише надісланий запит CallSub, а не підтвердження запуску або завершення.
- Збережіть приклад як окремий файл, завантажте його в IDE/менеджер і запускайте Main, щоб інші процедури потрапили до каталогу. WeightWatch/ManaWatch — повністю визначені тут навчальні процедури: три виміри ваги/мани з інтервалом UO.Wait(1000), тобто 1000 мс, висновок лише при вході у світ. Це не постійний моніторинг; пауза може розтягнути час. Для прикладу із двома завданнями має бути дозволено одночасний запуск процедур.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var registrationWeightWatch = RegisterRoutine("WeightWatch", WeightWatch);
var launched = StartIfIdle("WeightWatch");
while (UO.FunRunning("WeightWatch") != 0)
await WaitAsync(25);
return launched;
return null;
}
dynamic StartIfIdle(dynamic name)
{
if (!(Truth(UO.SubExists(name))))
{
return false;
}
if (Truth(UO.FunRunning(name)))
{
return false;
}
UO.CallSub(name);
return true;
}
void WeightWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Weight: " + Convert.ToString(UO.Weight()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Перший CallSub запускає WeightWatch, другий - ManaWatch. Запуски незалежні та не обмінюються локальними змінними; порядок їхнього виведення не гарантований.
- Збережіть приклад як окремий файл, завантажте його в IDE/менеджер і запускайте Main, щоб інші процедури потрапили до каталогу. WeightWatch/ManaWatch — повністю визначені тут навчальні процедури: три виміри ваги/мани з інтервалом UO.Wait(1000), тобто 1000 мс, висновок лише при вході у світ. Це не постійний моніторинг; пауза може розтягнути час. Для прикладу із двома завданнями має бути дозволено одночасний запуск процедур.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var registrationWeightWatch = RegisterRoutine("WeightWatch", WeightWatch);
var registrationManaWatch = RegisterRoutine("ManaWatch", ManaWatch);
UO.CallSub("WeightWatch");
UO.CallSub("ManaWatch");
while (UO.FunRunning("WeightWatch") != 0 || UO.FunRunning("ManaWatch") != 0)
await WaitAsync(25);
return null;
}
void WeightWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Weight: " + Convert.ToString(UO.Weight()));
}
UO.Wait(1000);
}
}
void ManaWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Mana: " + Convert.ToString(UO.Mana()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
private IDisposable RegisterRoutine(string name, Action handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Action<string[]> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<string[], Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: subrutineName (String)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.CallSub. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Exec:bridge.Exec(subrutineName).
Внутрішній код реалізації, не самостійний скрипт.
case "CallSub":
string called = Convert.ToString(arguments[0]) ?? "";
if (Exists(called)) Start(called);
else if (events is ICSharpScriptHost host && host.HasCSharpScript(called)) host.ExecuteCSharpScript("exec \"" + called + "\"");
else throw new ArgumentException($"Register the C# routine or load a C# script entry named '{called}' before calling it.");
return true;Внутрішній код реалізації, не самостійний скрипт.
public void CallSub(string subrutineName) => bridge.Exec(subrutineName);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.Date();Читає місцеву календарну дату комп'ютера числом YYMMDD. Зручний для назви денної серії дій або виявлення зміни дати.
Параметрів немає.
int YYMMDD: 2026-09-30 -> 260930. Розділювачів і початкових нулів, що зберігаються, немає. Це не тривалість, не Unix-час і не true/false.
- Параметрів немає, форм із аргументами немає. Порожні дужки лише читають час: виклик не чекає, не запускає таймер та не відправляє пакети у гру.
- RealTimeSource.Now читає DateTime.Now: місцеву дату/час комп'ютера, не UTC, не час шарду та не ігровий годинник. Часовий пояс, літній час та ручний переведення годинника впливають на результат. Кожен дзвінок фіксує окремий момент.
- Зберігаються лише дві останні цифри року: і 2000-01-01, і 2100-01-01 дають 101. Різні сторіччя не відрізняються. Окремі виклики Date та Time можуть потрапити по різні боки опівночі.
- Не віднімайте календарні коди для розрахунку затримки. Використовуйте Timer() та дві позначки одного запуску. Календарний годинник може перевестися назад.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.Date();
UO.Print("Date: " + Convert.ToString(result));Параметри та порядок виконання:
- Результат дзвінка без настройок зберігається один раз. sessionLabel - рядок на зразок harvest-260930. Print тільки показує назву: файл не створюється, збирання ресурсів не запускається.
var dateStamp = UO.Date();
var sessionLabel = "harvest-" + Convert.ToString(dateStamp);
UO.Print(sessionLabel);Параметри та порядок виконання:
- originalDate зберігає вихідну дату. Timer обмежує спостереження 60 секундами, UO.Wait(1000) дає перевірку приблизно раз на секунду. Зміна дати завершує Main. Приклад не чекає на півночі нескінченно і не стверджує, що змінився день на сервері.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var originalDate = UO.Date();
var started = Environment.TickCount;
while (Truth(Environment.TickCount - started < 60.0))
{
if (Truth(UO.Date() != originalDate))
{
UO.Print("Local date changed; end this batch");
return null;
}
await Delay(1000);
}
UO.Print("No date change observed within one minute");
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- MonthPart(stamp) показана цілком: розподіл із заокругленням вниз і MOD 100 витягують місяць. day - дві останні цифри; shortYear - Неповний рік. Для 260930 виходять 26, 9, 30.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var stamp = UO.Date();
var month = MonthPart(stamp);
var day = stamp % 100;
var shortYear = stamp / 10000;
UO.Print(Convert.ToString(shortYear) + "/" + Convert.ToString(month) + "/" + Convert.ToString(day));
return null;
}
dynamic MonthPart(dynamic stamp)
{
return stamp / 100 % 100;
}
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: int / Integer.
Під час виклику:
Внутрішній код реалізації, не самостійний скрипт.
public int Date()
{
var now = timeSource.Now;
return (now.Year % 100) * 10000 + now.Month * 100 + now.Day;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.Exec(object? parameters);Виконує текстову ігрову команду або запускає зареєстрований C#-делегат або завантажений C#-файл.
-
parameters- рядок команди: наприклад "useskill Hiding", "exec Worker 42" або "exec Child.csx::Main 'north gate' 42". Вираз C# на зразок 2+3 всередині рядка автоматично не обчислюється.
void: результату немає. Повернення керування не означає закінчення запуску або підтвердження ігрової дії сервером.
Значення UO.FunRunning(name) == 0 також можливе одразу після запиту скасування. Воно не означає, що блок finally попереднього callback уже завершився. Повторний CallSub або Exec того самого локального імені пропускається, поки попередній обробник фактично не завершить роботу.
- Спочатку перевіряється локальний реєстр RegisterRoutine. Підтримуються Name args, "exec Name args" та "_exec Name args". Делегат отримує string[]: аргумент 42 залишається рядком "42", а '00123' зберігає провідні нулі. Одинарні або подвійні лапки поєднують аргумент з пробілами; '' задає порожній рядок. Незакрита лапка викликає помилку. У цьому маршруті зворотний сліш зберігається буквально; не використовуйте синтаксис екранування C# усередині вже готового тексту команди.
- Локальний делегат запускається асинхронно. Для очікування його закінчення використовуйте FunRunning та WaitAsync. Повторний запуск активного імені не створює копію та не знімає паузу. Помилка помічника передається основному скрипту на контрольній точці.
- Явно завантажені файлові входи запускаються поточним менеджером із власним Args та часом життя. Саме прийняття запиту запуску ще означає, що файл закінчив роботу.
- Прості ігрові команди передаються native-диспетчеру. Там зберігаються контракти параметрів відповідної UO-команди; Print/Msg/Say/ConsolePrint/TextPrint об'єднують залишок рядка в текст. Для точних C#-типів та виразів використовуйте прямий виклик на кшталт UO.UseSkill("Hiding"). Невідома команда, невідповідні аргументи або лапки можуть викликати виняток, що перехоплюється try/catch.
- Псевдонім консолі: sayu → Say, closeuo → CloseHandle, CountOnGround → CountGround, clearignorelist → IgnoreReset, canceltarget → CancelTarget, cancelmove → MoveOff.
Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
RegisterRoutine("Hello", () => UO.Print("Hello from a routine"));
UO.Exec("exec Hello");
while (UO.FunRunning("Hello") != 0) await WaitAsync(25);Параметри та порядок виконання:
- Hiding - єдиний аргумент "UseSkill". При вході у світ клієнт надсилає запит використання навички; успіх приховування визначає сервер. Та ж операція прямим викликом: UO.UseSkill("Hiding").
UO.Exec("useskill Hiding");Параметри та порядок виконання:
- SelectSavedRoute визначено нижче та записує назву вибраного маршруту. Лапки навколо 00123 зберігають провідні нулі. Exec запускає зареєстрований делегат асинхронно. Цикл з FunRunning та WaitAsync явно очікує його закінчення, потім сценарій повертає рядок 00123. Це навчальне збереження імені, а чи не команда руху.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var registration = RegisterRoutine("SelectSavedRoute", (Action<string[]>)(arguments =>
{
if (arguments.Length == 1)
SelectSavedRoute(arguments[0]);
}));
UO.Exec("SelectSavedRoute '00123'");
while (UO.FunRunning("SelectSavedRoute") != 0)
await WaitAsync(25);
return UO.GetGlobal("manual", "savedRoute");
return null;
}
void SelectSavedRoute(dynamic name)
{
UO.SetGlobal("manual", "savedRoute", name);
}Параметри та порядок виконання:
- Запускайте цей C#-скрипт: RegisterRoutine пов'язує ім'я WeightWatch з оголошеною функцією поточного виконання. exec WeightWatch запускає три виміри ваги з інтервалом 1000 мс і не чекає їх завершення. Основний скрипт залишається активним, доки працює локальний помічник; помічник не має окремого індексу менеджера. Якщо завдання вже на паузі, повторний Exec її не відновлює.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var registrationWeightWatch = RegisterRoutine("WeightWatch", WeightWatch);
UO.Exec("exec WeightWatch");
while (UO.FunRunning("WeightWatch") != 0)
await WaitAsync(25);
return null;
}
void WeightWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Weight: " + Convert.ToString(UO.Weight()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
private IDisposable RegisterRoutine(string name, Action handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Action<string[]> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<string[], Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
}Параметри та порядок виконання:
- Замініть шлях існуючим C#-файлом зі своєю процедурою Main. startscript завантажує файл та запитує запуск Main. Лапки належать текстовій команді; зворотні сліші шляхи зберігаються. Помилки запуску дивіться в IDE, оскільки Exec не повертає підтвердження.
UO.Exec("startscript 'C:\\UO Scripts\\Gather.csx'");C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: parameters (String)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionRuntime.Exec. -
InjectionScript.Runtime.InjectionRuntime.Tokenize:Tokenize(parameters). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Exec:bridge.Exec(parts[1].Text). -
InjectionScript.Runtime.InjectionRuntime.TryHandleLegacyConsoleCommand:TryHandleLegacyConsoleCommand(command, rawArguments). -
InjectionScript.Runtime.InjectionRuntime.NormalizeConsoleAlias:NormalizeConsoleAlias(command). -
InjectionScript.Runtime.InjectionRuntime.IsRemainderTextCommand:IsRemainderTextCommand(command). -
InjectionScript.Runtime.InjectionRuntime.ToConsoleValue:ToConsoleValue(token.Text). -
InjectionScript.Runtime.InjectionRuntime.CallNativeSubrutine:CallNativeSubrutine(command, args).
Внутрішній код реалізації, не самостійний скрипт.
case "Exec":
var words = CommandWords(Convert.ToString(arguments[0]) ?? "");
if (words.Length == 0) return false;
int offset = words[0].Equals("exec", StringComparison.OrdinalIgnoreCase) || words[0].Equals("_exec", StringComparison.OrdinalIgnoreCase) ? 1 : 0;
if (words.Length > offset && Exists(words[offset]))
{ Start(words[offset], words.Skip(offset + 1).ToArray()); return true; }
if (words.Length > offset && events is ICSharpScriptHost scriptHost
&& (offset == 1 || scriptHost.HasCSharpScript(words[offset])))
{
string command = Convert.ToString(arguments[0]) ?? "";
if (words[0].Equals("_exec", StringComparison.OrdinalIgnoreCase)) command = "exec" + command.TrimStart()[5..];
scriptHost.ExecuteCSharpScript(command); return true;
}
return false;Внутрішній код реалізації, не самостійний скрипт.
public void Exec(string parameters)
{
ConsoleToken[] parts = Tokenize(parameters).ToArray();
if (parts.Length == 0)
return;
string command = parts[0].Text;
if (command.Equals("exec", StringComparison.OrdinalIgnoreCase))
{
if (parts.Length != 2 || string.IsNullOrWhiteSpace(parts[1].Text))
throw new NativeSubrutineException("Usage: exec script_function");
bridge.Exec(parts[1].Text);
return;
}
ConsoleToken[] arguments = parts.Skip(1).ToArray();
string[] rawArguments = arguments.Select(token => token.Text).ToArray();
if (TryHandleLegacyConsoleCommand(command, rawArguments))
return;
command = NormalizeConsoleAlias(command);
if (IsRemainderTextCommand(command) && rawArguments.Length > 0)
arguments = new[] { new ConsoleToken(string.Join(" ", rawArguments), true) };
else if (command.Equals("ColorPrint", StringComparison.OrdinalIgnoreCase) && rawArguments.Length > 1)
arguments = new[] { arguments[0], new ConsoleToken(string.Join(" ", rawArguments.Skip(1)), true) };
else if (command.Equals("CharPrint", StringComparison.OrdinalIgnoreCase) && rawArguments.Length > 2)
arguments = new[] { arguments[0], arguments[1], new ConsoleToken(string.Join(" ", rawArguments.Skip(2)), true) };
InjectionValue[] args = arguments.Select(token => token.Quoted
? new InjectionValue(token.Text) : ToConsoleValue(token.Text)).ToArray();
CallNativeSubrutine(command, args);
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.FunRunning(object? subrutineName);Перевіряє, чи виконується зареєстрований C#-callback із зазначеним ім'ям. Результат 1 включає ручну паузу; завершена чи скасовується завдання дає 0.
-
subrutineName— рядкове ім’я, задане RegisterRoutine. Пробіли по краях видаляються; пошук зареєстрованого імені не залежить від регістру.
int: 1 — умова виконана, 0 — не виконано. Збережіть результат одного виклику, якщо він потрібний кількох перевірок.
Значення UO.FunRunning(name) == 0 також можливе одразу після запиту скасування. Воно не означає, що блок finally попереднього callback уже завершився. Повторний CallSub або Exec того самого локального імені пропускається, поки попередній обробник фактично не завершить роботу.
- Реєстрація та завдання належать одному виконанню. Інший персонаж, профіль чи наступний запуск має власний реєстр.
- ?RegisterRoutine? приймає ?
Action?, ?Func<Task>? або делегат з масивом рядкових аргументів для ?Exec?. Видалення реєстрації не запускає код і унеможливлює подальший пошук імені. - Основний скрипт повинен залишатися активним, поки потрібні його помічники: після закінчення завдання скасовуються, а реєстрації та підписки звільняються.
- FunRunning не є індексом менеджера. GetScriptsList та GetScriptState описують самостійні запуски файлів; локальний callback окремого індексу не отримує.
- Помилка callback передається основному скрипту на наступній перевірці. WaitAsync, UO.Wait та інструментовані C#-цикли підтримують паузу, скасування та обробку черги подій.
Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
RegisterRoutine("Hello", async () => await WaitAsync(100));
UO.CallSub("Hello");
UO.Print("Running flag: " + UO.FunRunning("Hello"));
while (UO.FunRunning("Hello") != 0) await WaitAsync(25);Параметри та порядок виконання:
- Спочатку RegisterRoutine пов'язує ім'я з C#-функцією. FunRunning перевіряє завдання цього виконання, включаючи паузу. Основний скрипт залишається активним до завершення помічника.
var registration = RegisterRoutine("WeightWatch", WatchWeight);
if (UO.FunRunning("WeightWatch") == 0) UO.CallSub("WeightWatch");
while (UO.FunRunning("WeightWatch") != 0) await WaitAsync(25);
async Task WatchWeight()
{
for (int sample = 0; sample < 3; sample++)
{
UO.Print($"Weight: {UO.Weight()}");
await WaitAsync(250);
}
}Параметри та порядок виконання:
- Async-делегат змінює загальний лічильник через
Interlocked. Після FunRunning=0 результат читається черезVolatile. Це локальний callback; окремого індексу GetScriptsList у нього немає.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
int completed = 0;
var registration = RegisterRoutine("Worker", async () =>
{
await WaitAsync(150);
Interlocked.Exchange(ref completed, 1);
});
UO.CallSub("Worker");
UO.Print($"Worker active: {UO.FunRunning("Worker") != 0}");
while (UO.FunRunning("Worker") != 0)
await WaitAsync(25);
return Volatile.Read(ref completed) == 1;
return null;
}Параметри та порядок виконання:
- Terminate вибирає зареєстроване завдання поточного виконання. Очікування WaitAsync використовує її токен скасування.
finallyвиконує очищення; подальші ігрові дії скасованого завдання не допускаються.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
int cleanupDone = 0;
var registration = RegisterRoutine("Worker", async () =>
{
try
{
await WaitAsync(5000);
}
finally
{
Interlocked.Exchange(ref cleanupDone, 1);
}
});
UO.CallSub("Worker");
await WaitAsync(100);
if (UO.FunRunning("Worker") != 0)
UO.Terminate("Worker");
while (UO.FunRunning("Worker") != 0)
await WaitAsync(25);
while (Volatile.Read(ref cleanupDone) == 0)
await WaitAsync(25);
return true;
return null;
}
private IDisposable RegisterRoutine(string name, Action handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Action<string[]> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<string[], Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: subrutineName (String)
Результат: int / Integer.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.FunRunning. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.FunRunning:bridge.FunRunning(subrutineName).
Внутрішній код реалізації, не самостійний скрипт.
case "FunRunning":
string runningName = Convert.ToString(arguments[0]) ?? "";
result = IsRunning(runningName) || events is ICSharpScriptHost runningHost && runningHost.IsCSharpScriptRunning(runningName) ? 1 : 0;
return true;Внутрішній код реалізації, не самостійний скрипт.
public int FunRunning(string subrutineName) => bridge.FunRunning(subrutineName) ? 1 : 0;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetPauseScriptOnDisconnectStatus();Читає налаштування паузи скриптів при вимкненні менеджера.
Параметрів немає.
int 1 — PauseScriptsOnDisconnect включений; 0 — вимкнено.
- Читає прапор менеджера, що не поточну паузу окремого скрипта. Сам виклик не ставить та не знімає паузу.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
object? result = UO.GetPauseScriptOnDisconnectStatus();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Параметри та порядок виконання:
- Значення визначає налаштування менеджера.
var enabled = UO.GetPauseScriptOnDisconnectStatus();
UO.Print(Convert.ToString(enabled));Параметри та порядок виконання:
- Прапор налаштування та з'єднання читаються незалежно.
return RunScenario();
object? RunScenario()
{
var pauseOnDisconnect = UO.GetPauseScriptOnDisconnectStatus();
var online = UO.Connected();
UO.Print(Convert.ToString(pauseOnDisconnect) + " " + Convert.ToString(online));
return null;
}Параметри та порядок виконання:
- Змінна містить знімок налаштування на момент читання.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var saved = UO.GetPauseScriptOnDisconnectStatus();
await Delay(100);
UO.Print(Convert.ToString(saved));
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: dynamic / Any.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetPauseScriptOnDisconnectStatus:bridge.GetPauseScriptOnDisconnectStatus().
Внутрішній код реалізації, не самостійний скрипт.
case "getpausescriptondisconnectstatus": return new InjectionValue(bridge.GetPauseScriptOnDisconnectStatus());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
string UO.GetScriptName(object? scriptIndex);Читає відображене ім'я активного запуску.
-
scriptIndex— Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
string: отображаемое имя либо "", если индекса нет. У існуючого запуску ім'я також може бути явно встановлено в порожній рядок.
- Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
- Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
- "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
- ScriptIndex=0 — перший поточний запуск, який не обов'язково викликає скрипт. SetScriptName змінює ім'я, що відображається, не перейменовуючи файл.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.GetScriptName(0);
UO.Print("GetScriptName: " + Convert.ToString(result));Параметри та порядок виконання:
- Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
- ScriptIndex=0 — перший поточний запуск, який не обов'язково викликає скрипт. SetScriptName змінює ім'я, що відображається, не перейменовуючи файл.
- string: отображаемое имя либо "", если индекса нет. У існуючого запуску ім'я також може бути явно встановлено в порожній рядок.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
var index = 0;
var name = UO.GetScriptName(index);
UO.Print(name);Параметри та порядок виконання:
- Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. UO.Wait(250), де він використовується, чекає 250 мілісекунд.
- ScriptIndex=0 — перший поточний запуск, який не обов'язково викликає скрипт. SetScriptName змінює ім'я, що відображається, не перейменовуючи файл.
- string: отображаемое имя либо "", если индекса нет. У існуючого запуску ім'я також може бути явно встановлено в порожній рядок.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
return RunScenario();
object? RunScenario()
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
var name = UO.GetScriptName(index);
UO.Print(Convert.ToString(index) + " = " + name);
}
return null;
}Параметри та порядок виконання:
- Під Main наведено функцію повністю. Її параметри та результат пояснюються окремо від API-команди, яку вона викликає.
- DescribeScript перевіряє стан та поєднує ім'я з шляхом. Між дзвінками можлива зупинка; "missing" - значення нашої функції, а не результат GetScriptName.
- string: отображаемое имя либо "", если индекса нет. У існуючого запуску ім'я також може бути явно встановлено в порожній рядок.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
UO.Print(DescribeScript(0));
return null;
}
dynamic DescribeScript(dynamic index)
{
if (Truth(UO.GetScriptState(index) == 0))
{
return "missing";
}
return UO.GetScriptName(index) + " | " + UO.GetScriptPath(index);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptIndex (Any)
Результат: string / String.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetScriptName:bridge.GetScriptName(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
case "getscriptname": return new InjectionValue(bridge.GetScriptName(Arg(0)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
string UO.GetScriptPath(object? scriptIndex);Читає шлях вихідного файлу активного запуску.
-
scriptIndex— Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
string: збережений шлях вихідного файлу чи " " , якщо індексу немає. При запуску файлу зазвичай повний шлях; у команди або вихідного файлу в пам'яті звичайного файлу може не бути.
- Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
- Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
- "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
- ScriptIndex=0 вибирає перший поточний запуск. Результат указує його вихідник; команда не відкриває, не зберігає та не запускає цей файл.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.GetScriptPath(0);
UO.Print("GetScriptPath: " + Convert.ToString(result));Параметри та порядок виконання:
- Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
- ScriptIndex=0 вибирає перший поточний запуск. Результат указує його вихідник; команда не відкриває, не зберігає та не запускає цей файл.
- string: збережений шлях вихідного файлу чи " " , якщо індексу немає. При запуску файлу зазвичай повний шлях; у команди або вихідного файлу в пам'яті звичайного файлу може не бути.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
var index = 0;
var path = UO.GetScriptPath(index);
if (Truth(path!=""))
{
UO.Print(path);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. UO.Wait(250), де він використовується, чекає 250 мілісекунд.
- ScriptIndex=0 вибирає перший поточний запуск. Результат указує його вихідник; команда не відкриває, не зберігає та не запускає цей файл.
- string: збережений шлях вихідного файлу чи " " , якщо індексу немає. При запуску файлу зазвичай повний шлях; у команди або вихідного файлу в пам'яті звичайного файлу може не бути.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
return RunScenario();
object? RunScenario()
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
UO.Print(UO.GetScriptName(index) + " -> " + UO.GetScriptPath(index));
}
return null;
}Параметри та порядок виконання:
- Під Main наведено функцію повністю. Її параметри та результат пояснюються окремо від API-команди, яку вона викликає.
- ReadScriptPath підставляє параметр fallback тільки при порожньому шляху. Це окрема функція, а не нове навантаження GetScriptPath.
- string: збережений шлях вихідного файлу чи " " , якщо індексу немає. При запуску файлу зазвичай повний шлях; у команди або вихідного файлу в пам'яті звичайного файлу може не бути.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
UO.Print(ReadScriptPath(0, "path unavailable"));
return null;
}
dynamic ReadScriptPath(dynamic index, dynamic fallback)
{
var path = UO.GetScriptPath(index);
if (Truth(path == ""))
{
return fallback;
}
return path;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptIndex (Any)
Результат: string / String.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetScriptPath:bridge.GetScriptPath(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
case "getscriptpath": return new InjectionValue(bridge.GetScriptPath(Arg(0)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetScriptState(object? scriptIndex);Читає стан виконання за індексом.
-
scriptIndex— Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
int — код стану: 0 = ні/невідомо, 1 = виконується, 2 = пауза. Це не bool: явно порівнюйте з 1 або 2.
- Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
- Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
- "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
- Враховується ручна/налагоджувальна пауза та налаштована пауза при вимкненні. Стан 1 не гарантує, що скрипт прямо зараз витрачає процесор або отримує дані сервера.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.GetScriptState(0);
UO.Print("GetScriptState: " + Convert.ToString(result));Параметри та порядок виконання:
- Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
- Враховується ручна/налагоджувальна пауза та налаштована пауза при вимкненні. Стан 1 не гарантує, що скрипт прямо зараз витрачає процесор або отримує дані сервера.
- int — код стану: 0 = ні/невідомо, 1 = виконується, 2 = пауза. Це не bool: явно порівнюйте з 1 або 2.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
int state = UO.GetScriptState(0);
string text = state switch
{
1 => "running",
2 => "paused",
_ => "unknown"
};
UO.Print(text);Параметри та порядок виконання:
- Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. UO.Wait(250), де він використовується, чекає 250 мілісекунд.
- Враховується ручна/налагоджувальна пауза та налаштована пауза при вимкненні. Стан 1 не гарантує, що скрипт прямо зараз витрачає процесор або отримує дані сервера.
- int — код стану: 0 = ні/невідомо, 1 = виконується, 2 = пауза. Це не bool: явно порівнюйте з 1 або 2.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
return RunScenario();
object? RunScenario()
{
var paused = 0;
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptState(index) == 2))
{
paused += 1;
}
}
UO.Print(Convert.ToString(paused));
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Під Main наведено функцію повністю. Її параметри та результат пояснюються окремо від API-команди, яку вона викликає.
- "IsScriptActive" перетворює "1" і "2" в true, а "0" в false. Сама GetScriptState, як і раніше, повертає числовий код стану.
- int — код стану: 0 = ні/невідомо, 1 = виконується, 2 = пауза. Це не bool: явно порівнюйте з 1 або 2.
- Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
if (Truth(Truth(IsScriptActive(0)) == true))
{
UO.Print("running or paused");
}
else
{
UO.Print("not active");
}
return null;
}
dynamic IsScriptActive(dynamic index)
{
var state = UO.GetScriptState(index);
return Truth(state == 1) || Truth(state == 2);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptIndex (Any)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetScriptState:bridge.GetScriptState(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
case "getscriptstate": return new InjectionValue(bridge.GetScriptState(Arg(0)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.GetScriptsCount();Вважає активні запуски у цьому клієнті.
Параметрів немає.
int >= 0: кількість активних запусків, включаючи призупинені. Ця кількість, а не bool і не індекс скрипту.
- Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
- Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
- "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
- Аргументів немає. Підрахунок не сортує список та не змінює стан запусків.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.GetScriptsCount();
UO.Print("GetScriptsCount: " + Convert.ToString(result));Параметри та порядок виконання:
- Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
- Аргументів немає. Підрахунок не сортує список та не змінює стан запусків.
- int >= 0: кількість активних запусків, включаючи призупинені. Ця кількість, а не bool і не індекс скрипту.
var count = UO.GetScriptsCount();
UO.Print(Convert.ToString(count));Параметри та порядок виконання:
- Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. UO.Wait(250), де він використовується, чекає 250 мілісекунд.
- Аргументів немає. Підрахунок не сортує список та не змінює стан запусків.
- int >= 0: кількість активних запусків, включаючи призупинені. Ця кількість, а не bool і не індекс скрипту.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var before = UO.GetScriptsCount();
await Delay(250);
var after = UO.GetScriptsCount();
UO.Print(Convert.ToString(after - before));
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));Параметри та порядок виконання:
- Під Main наведено функцію повністю. Її параметри та результат пояснюються окремо від API-команди, яку вона викликає.
- HasOtherScripts порівнює кількість з 1: скрипт, що викликає, зазвичай займає один запис. На відміну від GetScriptsCount, допоміжна функція повертає true/false.
- int >= 0: кількість активних запусків, включаючи призупинені. Ця кількість, а не bool і не індекс скрипту.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
if (Truth(HasOtherScripts()))
{
UO.Print("Other executions are active");
}
else
{
UO.Print("No other active executions");
}
return null;
}
dynamic HasOtherScripts()
{
var count = UO.GetScriptsCount();
return count > 1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetScriptsCount:bridge.GetScriptsCount().
Внутрішній код реалізації, не самостійний скрипт.
case "getscriptscount": return new InjectionValue(bridge.GetScriptsCount());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetScriptsList();Повертає поточні числові індекси скриптів.
Параметрів немає.
Array з int: індекси 0..N-1 або порожній масив. Елементи – числа, а не імена та не текстові записи.
- Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
- Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
- "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
- Аргументів немає. Кожне число передавайте у відповідний getter імені, шляху чи стану. Отриманий масив – окремий знімок; його зміна не керує скриптами.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
object? result = UO.GetScriptsList();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Параметри та порядок виконання:
- Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
- Аргументів немає. Кожне число передавайте у відповідний getter імені, шляху чи стану. Отриманий масив – окремий знімок; його зміна не керує скриптами.
- Array з int: індекси 0..N-1 або порожній масив. Елементи – числа, а не імена та не текстові записи.
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
UO.Print(Convert.ToString(index) + ": " + UO.GetScriptName(index));
}Параметри та порядок виконання:
- Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. UO.Wait(250), де він використовується, чекає 250 мілісекунд.
- Аргументів немає. Кожне число передавайте у відповідний getter імені, шляху чи стану. Отриманий масив – окремий знімок; його зміна не керує скриптами.
- Array з int: індекси 0..N-1 або порожній масив. Елементи – числа, а не імена та не текстові записи.
return RunScenario();
object? RunScenario()
{
var indices = UO.GetScriptsList();
if (Truth(ArrayLength(indices) > 0))
{
var firstIndex = indices[0];
UO.Print(UO.GetScriptPath(firstIndex));
}
return null;
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Під Main наведено функцію повністю. Її параметри та результат пояснюються окремо від API-команди, яку вона викликає.
- FindNamedScript перебирає поточні індекси і повертає перший точне збіг відображуваного імені або -1. Імена можуть повторюватися, індекси можуть пізніше зрушити.
- Array з int: індекси 0..N-1 або порожній масив. Елементи – числа, а не імена та не текстові записи.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var index = FindNamedScript("Mining");
if (Truth(index >= 0))
{
UO.Print(Convert.ToString(index));
}
else
{
UO.Print("Name not found");
}
return null;
}
dynamic FindNamedScript(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: dynamic / Array.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetScriptsList:bridge.GetScriptsList().
Внутрішній код реалізації, не самостійний скрипт.
case "getscriptslist": return new InjectionValue(bridge.GetScriptsList().Select(value => new InjectionValue(value)).ToArray());Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.Launch(object? file);
int UO.Launch(object? file, object? parameters);
int UO.Launch(object? file, object? parameters, object? workingDirectory);
int UO.Launch(object? file, object? parameters, object? workingDirectory, object? hidden);-
file— Обов'язковий шлях/ім'я програми чи документа; перетворюється на текст, крайні прогалини видаляються. Порожнє значення дає 0 та повідомлення про помилку. Для точного вибору програми скористайтеся повним шляхом; зовнішні лапки до самого файлу додавати не потрібно. -
workingDirectory— необов'язкова робоча папка процесу. Під час пропуску або порожнього рядка береться папка поточного скрипту. Якщо runtime немає такої папки, bridge використовує поточну робочу папку клієнта. Це не завжди папка гри або EXE клієнта. -
hidden— Необов'язкове логічне значення за промовчанням false. true відключає відкриття через оболонку ОС та запитує запуск без вікна консолі; потрібен виконуваний файл. false дозволяє асоціації документів. Сама GUI-програма все одно може показати своє вікно.
int: 1 (true), якщо Process.Start повернув об'єкт процесу; інакше 0 (false). У C# перевіряйте result == 1 або result != 0; int не можна безпосередньо порівнювати з true. Це не PID, не код завершення та не підтвердження виконання роботи. При виключенні виводиться помилка та повертається 0. При відкритті документа через працюючу програму ОС іноді не повертає новий процес: 0 у разі не доводить, що документ не відкрився.
- Допустимі лише перевантаження від одного до чотирьох аргументів у зазначеному порядку. Щоб встановити hidden і залишити робочу папку за промовчанням, передайте порожній рядок третім аргументом. Перетворення file/parameters/workingDirectory на текст не перевіряють існування файлу заздалегідь.
- Типова папка визначається поточним виконуваним скриптом. При hidden=true відносний шлях програми спочатку перевіряється щодо workingDirectory. Пошук неповного імені ОС та асоціації залежить від системи; повний шлях усуває неоднозначність. Якщо робоча папка або програма недоступні, запуск може завершитися помилкою.
- Зовнішній процес працює незалежно. Launch не чекає на його завершення, не читає stdout/stderr і не завершує його при зупинці скрипта. true для hidden – запит способу запуску, а не гарантія невидимості будь-яких вікон. Об'єкт Process після звільнення запиту; сама запущена програма продовжує працювати.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.Launch("loot-report.txt");
UO.Print("Launch: " + Convert.ToString(result));Параметри та порядок виконання:
- Покладіть існуючий loot-report.txt поряд зі скриптом. ОС відкриває його програмою, призначеною для .txt. Main повертає результат запиту Launch, а не вміст звіту та не підтвердження його прочитання.
var started = UO.Launch("loot-report.txt");
return started;Параметри та порядок виконання:
- Папка та звіт повинні існувати; замініть їх своїми. Chr(34) укладає повний шлях звіту в подвійні лапки всередині arguments. notepad.exe має бути доступний системі. false дозволяє звичайне вікно редактора.
return RunScenario();
object? RunScenario()
{
var report = "C:\\UO Scripts\\loot report.txt";
var arguments = Chr(34) + report + Chr(34);
return UO.Launch("notepad.exe", arguments, "C:\\UO Scripts", false);
return null;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();Параметри та порядок виконання:
- Приклад Windows запускає вбудовану cmd.exe. У папці скрипта створюється або перезаписується log-files.txt зі списком *.log. Порожній третій аргумент зберігає папку скрипта, true приховує консоль. true з Main означає лише запуск: файл може бути ще не готовий, а відсутність *.log або помилка утиліти не змінюють вже отриманий результат Launch.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var started = UO.Launch("cmd.exe", "/d /c dir /b *.log > log-files.txt", "", true);
if (Truth(started == 0))
{
return false;
}
return true;
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: file (Any)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.Register [Launch]. -
InjectionScript.Runtime.InjectionApiUO.CompactLaunch:CompactLaunch(values).
Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.
Внутрішній код реалізації, не самостійний скрипт.
values => new InjectionValue(CompactLaunch(values))Параметри: file (Any), parameters (Any)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.Register [Launch]. -
InjectionScript.Runtime.InjectionApiUO.CompactLaunch:CompactLaunch(values).
Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.
Внутрішній код реалізації, не самостійний скрипт.
values => new InjectionValue(CompactLaunch(values))Параметри: file (Any), parameters (Any), workingDirectory (Any)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.Register [Launch]. -
InjectionScript.Runtime.InjectionApiUO.CompactLaunch:CompactLaunch(values).
Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.
Внутрішній код реалізації, не самостійний скрипт.
values => new InjectionValue(CompactLaunch(values))Параметри: file (Any), parameters (Any), workingDirectory (Any), hidden (Any)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.Register [Launch]. -
InjectionScript.Runtime.InjectionApiUO.CompactLaunch:CompactLaunch(values).
Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.
Внутрішній код реалізації, не самостійний скрипт.
values => new InjectionValue(CompactLaunch(values))Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.PauseResumeScript(object? scriptIndex);Перемикає ручну паузу активного запуску. Використовуйте для тимчасової зупинки видобутку чи іншої процедури без втрати поточного виконання.
-
scriptIndex— Обов'язковий ScriptIndex — поточний індекс запуску: 0 позначає перший, далі 1, 2… Отримуйте його через GetScriptsList; це не serial, ім'я файлу і не результат StartScript. Негативний/відсутній індекс нічого не змінює.
void — значення, що повертається, немає. Не порівнюйте дзвінок з true/1. Стан перевіряйте окремим читанням GetScriptState; результат такого читання - "0" (немає запуску), "1" (працює), "2" (пауза).
- Працює лише із запусками поточного сеансу. Відкрита вкладка без виконання не є активним запуском. Зупинка не видаляє вихідний файл і не вимикає з'єднання з сервером.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
- Це перемикач, а не команда "завжди продовжити". Ручна та автоматична паузи незалежні: перемикання ручного не знімає паузу розриву зв'язку. Код 2 не пояснює причини паузи. Якщо зупинити таким чином власний запуск, наступний виклик для його продовження він сам не зможе виконати; відновлюйте з IDE/менеджера або іншого скрипту.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
for (int index = 0; index < UO.GetScriptsCount(); index++)
if (UO.GetScriptName(index) == "Worker")
{ UO.PauseResumeScript(index); break; }Параметри та порядок виконання:
- MineOre — приклад відображеного імені процедури, що вже працює. FindNamedRun повертає перший збіглий індекс або -1. Викликайте з іншого контролера; повторний дзвінок змінює ручну паузу назад.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
var index = FindNamedRun("MineOre");
if (Truth(index >= 0))
{
UO.PauseResumeScript(index);
}
dynamic FindNamedRun(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Перевірка == 1 обмежує дію працюючим запуском. Значення «2» не використовується як вказівка «зняти ручну паузу», тому що воно може означати відсутність зв'язку.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return RunScenario();
object? RunScenario()
{
var index = FindNamedRun("MineOre");
if (Truth(index >= 0))
{
if (Truth(UO.GetScriptState(index) == 1))
{
UO.PauseResumeScript(index);
}
}
return null;
}
dynamic FindNamedRun(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Замініть абсолютний шлях своїм. FindFileRun порівнює шляхи без урахування регістру та повертає перший запуск цього файлу; в одному файлі може виконуватися кілька процедур.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var wantedPath = "D:/Game/AutoLoad/Scripts/Worker.csx";
var index = FindFileRun(wantedPath);
if (Truth(index >= 0))
{
UO.PauseResumeScript(index);
}
return null;
}
dynamic FindFileRun(dynamic wantedPath)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(Convert.ToString(ReplaceText(UO.GetScriptPath(index), Chr(92), "/")) == Convert.ToString(ReplaceText(wantedPath, Chr(92), "/"))))
{
return index;
}
}
return -1;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string ReplaceText(object? value, object? oldValue, object? newValue) => (Convert.ToString(value) ?? "").Replace(Convert.ToString(oldValue) ?? "", Convert.ToString(newValue) ?? "");
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptIndex (Any)
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.PauseResumeScript:bridge.PauseResumeScript(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
case "pauseresumescript": bridge.PauseResumeScript(Arg(0)); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.SetEvent(object? name, object? stateValue);
void UO.SetEvent(object? name, object? stateValue, object? repeatOrHandler);
void UO.SetEvent(object? nameValue, object? stateValue, object? repeatValue, object? subNameValue);Включає або вимикає спостереження за змінами стану персонажа і дозволяє вибрати одноразову або реакцію, що повторюється. Наприклад, можна один раз скасувати target, що залишився, після смерті або отримувати попередження про низьку витривалість. Оброблювач задається окремо від умови; основний скрипт повинен продовжувати виконувати UO.Wait.
-
name— Рядок з одним із п'яти імен: ChangeHitPoints, ChangeMana, ChangeStamina, Death, SeeNewPlayer. Реєстр не важливий; допустимо префікс ev, наприклад evChangeMana. Прогалини по краях видаляються. Числового каталогу подій немає; довільне ім'я не створює нової події. -
nameValue- Те ж ім'я події, що name; це назва першого параметра у формі із чотирма аргументами, не додаткове значення. -
stateValue— true/1 включає спостереження, false/0 знімає передплату. Передавайте логічні значення без лапок. При числовому перетворенні будь-яке ненульове ціле включає спостереження. Відключення не чекає та не зупиняє вже запущений обробник. -
repeatOrHandler— Третій аргумент має два призначення. Нечисловий непустий рядок, наприклад "OnManaChanged", задає обробник з автоматичним повторенням. Число/bool задає лише повтор: false/0 — одне спрацьовування, true/1 — повторювати; обробник у цій формі не призначається. Рядок "1" теж числова і не є ім'ям процедури. Для одноразового обробника використовуйте чотири аргументи. -
repeatValue— У формі з чотирма аргументами: false/0 — видалити підписку після першого виявленого переходу, true/1 — залишити її для наступних змін. Одноразова передплата знімається і тоді, коли обробник не знайдено або менеджер відхилив його запуск; не плутайте виявлення події з успішним завершенням процедури.
void - значення немає. Викликайте окремим рядком, без var result = і без порівняння з true/1. Завершення реєстрації не підтверджує, що обробник знайдено, запущено або що сервер здійснив дію. Якщо ім'я процедури не знайдено у випадку, виклик не відбувається.
- Два аргументи: false відключає подію; true включає повторюване спостереження без обробника. Ніяка процедура з іменем, що збігається, автоматично не підставляється. Ця форма не повертає виявлений факт і не замінює перевірку HP/Mana/Dead.
- Чотири аргументи явно задають ім'я події, включення, повторення та обробник. Обидва логічні параметри пишуться без лапок. false/0 = one-shot: підписка знімається після першого виявленого переходу, а не після закінчення оброблювача.
- Повторна реєстрація однієї події замінює його попередні налаштування та запам'ятовує поточний стан як нову точку відліку. Підписки SetEvent та SetEventProc на одне нормалізоване ім'я всередині одного скрипта використовують один запис, який не накопичується.
- ChangeHitPoints порівнює поточне HP self з попереднім знімком; спрацьовує і за втрати, і за відновлення здоров'я. ChangeMana та ChangeStamina аналогічно реагують в обидві сторони. Це не тільки шкода, витрата мани чи втома.
- Death спрацьовує під час переходу живий → мертвий. Реєстрація вже мертвого персонажа не викликає обробник одразу; повторна смерть після воскресіння може спричинити його знову.
- SeeNewPlayer порівнює набір завантажених mobiles, виключаючи 0 та self. Назва не означає перевірку реального гравця: сюди входять NPC та істоти. Один або кілька нових serial за одну перевірку викликають одну спробу запуску. Повернення з завантаженого набору mobile також може вважатися новою появою. ID не передається обробнику - потрібні об'єкти треба знайти окремо.
- UO.Wait та WaitAsync ділять очікування на інтервали до 25 мс і після кожного перевіряє події; UO.Wait(0) також виконує перевірку. Це опитування доступного стану, а не перехоплення кожного мережного пакета: швидка зміна та повернення між перевірками може бути пропущено. У обчислювальному циклі без UO.Wait або після завершення основного скрипту постійного спостереження немає.
- Ім'я обробника заздалегідь зв'язується з C#-делегатом через RegisterRoutine. Callback виконується асинхронно у цій сесії; одне завдання не накладається сама на себе. Після закінчення основного скрипта її подальші дії заборонені.
- Підписка відноситься до екземпляра виконуваного скрипта. Знімайте її в Main, який її створив: однойменна команда всередині окремо запущеного оброблювача змінить власні підписки. Скасування реєстрації не зупиняє вже запущений обробник. Використовуйте try/
finallyдля звичайного виходу або помилки, що обробляється; примусова зупинка також припиняє подальше опитування цього сценарію. - Невідоме непусте ім'я події під час реєстрації відхиляється із системним повідомленням. Порожнє ім'я нічого не робить. Наявність оброблювача перевіряється лише при спрацьовуванні; помилку в його імені краще виявити заздалегідь через SubExists та перевірку скрипту в IDE.
У C# обробник потрібно явно зареєструвати: RegisterRoutine("Handler", Handler). Зміни HP, мани та витривалості надходять через чергу native-подій; Death та SeeNewPlayer перевіряються за знімками локального світу. Прямі підписки з аргументами доступні через SubscribeEvent("UO.JournalEntry", handler) та аналогічні native-імена. Усі підписки звільняються після завершення або скасування цього виконання.
Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
RegisterRoutine("HealthChanged", () => UO.Print("HP changed"));
UO.SetEvent("ChangeHitPoints", true, false, "HealthChanged");
await WaitAsync(5000);Параметри та порядок виконання:
- Спостереження триває вісім секунд. Death вже мертвого персонажа не викликає негайно обробник. Друга подія смерті після воскресіння у цьому прикладі вже не опрацьовується.
- Оброблювач перевіряє активний курсор мети в момент виконання і лише тоді викликає CancelTarget. Підготовлена черга без активного курсору у цьому прикладі не скасовується. Скрипт не воскресає персонажа, не зупиняє всі скрипти та не завершує Main. Не запускайте приклад, якщо хочете зберегти активну мету.
var registrationOnFirstDeath = RegisterRoutine("OnFirstDeath", OnFirstDeath);
UO.SetEvent("Death", true, false, "OnFirstDeath");
try
{
UO.Wait(8000);
}
finally
{
UO.SetEvent("Death", false);
}
void OnFirstDeath()
{
if (Truth(UO.Targeting()))
{
UO.CancelTarget();
UO.Print("Death detected: active targeting cancelled");
}
else
{
UO.Print("Death detected: no active target");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- 24 × 250 мс - шість секунд. 10 — наш поріг в обробнику, не додатковий аргумент SetEvent. Зростання витривалості також викликає обробник, але при значенні від 10 повідомлення не виводиться.
- "true", "OnFatigue" відрізняється від "true", "true": останній варіант задає повторення без процедури. Скрипт не підвищує витривалість та не змінює швидкість сервера.
return RunScenario();
object? RunScenario()
{
var registrationOnFatigue = RegisterRoutine("OnFatigue", OnFatigue);
UO.SetEvent("evChangeStamina", true, "OnFatigue");
try
{
for (int tick = (int)(1); tick <= 24; tick += (int)(1))
{
UO.Wait(250);
}
}
finally
{
UO.SetEvent("ChangeStamina", false);
}
return null;
}
void OnFatigue()
{
var staminaNow = UO.Stamina();
if (Truth(staminaNow < 10))
{
UO.Print("Stamina is " + Convert.ToString(staminaNow) + ": consider resting");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Перші дві секунди кожна виявлена зміна викликає OnManaLog. Наступні три секунди використовується OnLowMana. Реєстрація другого оброблювача сама собою його не запускає.
- Заміна не перериває вже запущену стару процедуру. Ці короткі обробники не використовують локальні змінні Main. При забороні накладання процедур менеджер може відхилити запуск - для такого режиму перевіряйте Mana прямо в Main.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var registrationOnManaLog = RegisterRoutine("OnManaLog", OnManaLog);
var registrationOnLowMana = RegisterRoutine("OnLowMana", OnLowMana);
UO.SetEvent("ChangeMana", true, true, "OnManaLog");
try
{
UO.Wait(2000);
UO.SetEvent("ChangeMana", true, true, "OnLowMana");
UO.Wait(3000);
}
finally
{
UO.SetEvent("ChangeMana", false);
}
return null;
}
void OnManaLog()
{
UO.Print("Mana now: " + Convert.ToString(UO.Mana()));
}
void OnLowMana()
{
if (Truth(UO.Mana() < 20))
{
UO.Print("Mana below 20: check the cost before casting");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
private IDisposable RegisterRoutine(string name, Action handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Action<string[]> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<string[], Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: name (Any), stateValue (Any)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.SetEvent. -
InjectionScript.Runtime.InjectionApiUO.SetEvent:SetEvent(name, stateValue, InjectionValue.True, new InjectionValue(string.Empty)).
Внутрішній код реалізації, не самостійний скрипт.
case "SetEvent": SetStateEvent(arguments); return true;Внутрішній код реалізації, не самостійний скрипт.
public void SetEvent(InjectionValue name, InjectionValue stateValue)
=> SetEvent(name, stateValue, InjectionValue.True, new InjectionValue(string.Empty));Параметри: name (Any), stateValue (Any), repeatOrHandler (Any)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.SetEvent. -
InjectionScript.Runtime.InjectionValue.ToString:repeatOrHandler.ToString(). -
InjectionScript.Runtime.NumberConversions.TryStr2Int:NumberConversions.TryStr2Int(raw, out _). -
InjectionScript.Runtime.InjectionApiUO.SetEvent:SetEvent(name, stateValue, InjectionValue.True, repeatOrHandler).
Внутрішній код реалізації, не самостійний скрипт.
case "SetEvent": SetStateEvent(arguments); return true;Внутрішній код реалізації, не самостійний скрипт.
public void SetEvent(InjectionValue name, InjectionValue stateValue, InjectionValue repeatOrHandler)
{
string raw = repeatOrHandler.ToString() ?? string.Empty;
if (!string.IsNullOrWhiteSpace(raw) && !NumberConversions.TryStr2Int(raw, out _))
SetEvent(name, stateValue, InjectionValue.True, repeatOrHandler);
else
SetEvent(name, stateValue, repeatOrHandler, new InjectionValue(string.Empty));
}Параметри: nameValue (Any), stateValue (Any), repeatValue (Any), subNameValue (Any)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.SetEvent. -
InjectionScript.Runtime.InjectionApiUO.NormalizeLegacyEventName:NormalizeLegacyEventName(nameValue.ToString()). -
InjectionScript.Runtime.InjectionValue.ToString:nameValue.ToString(). -
InjectionScript.Runtime.NumberConversions.ToInt:NumberConversions.ToInt(stateValue). -
InjectionScript.Runtime.InjectionApiUO.IsSupportedLegacyEventName:IsSupportedLegacyEventName(name). -
InjectionScript.Runtime.InjectionApiUO.SystemMessage:SystemMessage($"SetEvent: unsupported event '{name}'. Supported: SeeNewPlayer, Death, ChangeHitPoints, ChangeMana, ChangeStamina."). -
InjectionScript.Runtime.InjectionApiUO.NormalizeLegacyEventHandler:NormalizeLegacyEventHandler(subNameValue.ToString()). -
InjectionScript.Runtime.InjectionApiUO.CaptureLegacyEventSnapshot:CaptureLegacyEventSnapshot(subscription).
Внутрішній код реалізації, не самостійний скрипт.
case "SetEvent": SetStateEvent(arguments); return true;Внутрішній код реалізації, не самостійний скрипт.
public void SetEvent(InjectionValue nameValue, InjectionValue stateValue, InjectionValue repeatValue, InjectionValue subNameValue)
{
string name = NormalizeLegacyEventName(nameValue.ToString());
if (string.IsNullOrEmpty(name))
return;
bool enabled = NumberConversions.ToInt(stateValue) != 0;
eventStates[name] = enabled ? 1 : 0;
if (!enabled)
{
legacyEvents.Remove(name);
return;
}
if (!IsSupportedLegacyEventName(name))
{
eventStates[name] = 0;
legacyEvents.Remove(name);
SystemMessage($"SetEvent: unsupported event '{name}'. Supported: SeeNewPlayer, Death, ChangeHitPoints, ChangeMana, ChangeStamina.");
return;
}
var subscription = new LegacyEventSubscription
{
Name = name,
Repeat = NumberConversions.ToInt(repeatValue) != 0,
Handler = NormalizeLegacyEventHandler(subNameValue.ToString())
};
CaptureLegacyEventSnapshot(subscription);
legacyEvents[name] = subscription;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.SetEventProc(object? eventname, object? procname);Призначає процедуру, яку клієнт запускатиме при зміні стану, що спостерігається: наприклад, при втраті здоров'я, зміні мани або появі нового mobile. Дозволяє відокремити реакцію від основного циклу. Реєстрація сама нічого не запускає: Основний скрипт має залишатися активним; C#-контрольні точки, WaitAsync та UO.Wait обробляють події.
-
eventname— Рядок з одним із п'яти імен: ChangeHitPoints, ChangeMana, ChangeStamina, Death, SeeNewPlayer. Реєстр не важливий; допустимо префікс ev, наприклад evChangeMana. Прогалини по краях видаляються. Числового каталогу подій немає; довільне ім'я не створює нової події.
void - значення немає. Викликайте окремим рядком, без var result = і без порівняння з true/1. Завершення реєстрації не підтверджує, що обробник знайдено, запущено або що сервер здійснив дію. Якщо ім'я процедури не знайдено у випадку, виклик не відбувається.
- Обидва аргументи є обов'язковими. Підписка повторюється: нові виявлені зміни викликають нові спроби запуску. В одному скрипті, що виконується, на одне нормалізоване ім'я події призначається один обробник; повторна реєстрація замінює його та оновлює початковий знімок. SetEventProc(event, "") знімає передплату в цьому ж скрипті. Для одноразової реакції використовуйте SetEvent(event, true, false, "Handler").
- ChangeHitPoints порівнює поточне HP self з попереднім знімком; спрацьовує і за втрати, і за відновлення здоров'я. ChangeMana та ChangeStamina аналогічно реагують в обидві сторони. Це не тільки шкода, витрата мани чи втома.
- Death спрацьовує під час переходу живий → мертвий. Реєстрація вже мертвого персонажа не викликає обробник одразу; повторна смерть після воскресіння може спричинити його знову.
- SeeNewPlayer порівнює набір завантажених mobiles, виключаючи 0 та self. Назва не означає перевірку реального гравця: сюди входять NPC та істоти. Один або кілька нових serial за одну перевірку викликають одну спробу запуску. Повернення з завантаженого набору mobile також може вважатися новою появою. ID не передається обробнику - потрібні об'єкти треба знайти окремо.
- UO.Wait та WaitAsync ділять очікування на інтервали до 25 мс і після кожного перевіряє події; UO.Wait(0) також виконує перевірку. Це опитування доступного стану, а не перехоплення кожного мережного пакета: швидка зміна та повернення між перевірками може бути пропущено. У обчислювальному циклі без UO.Wait або після завершення основного скрипту постійного спостереження немає.
- Ім'я обробника заздалегідь зв'язується з C#-делегатом через RegisterRoutine. Callback виконується асинхронно у цій сесії; одне завдання не накладається сама на себе. Після закінчення основного скрипта її подальші дії заборонені.
- Підписка відноситься до екземпляра виконуваного скрипта. Знімайте її в Main, який її створив: однойменна команда всередині окремо запущеного оброблювача змінить власні підписки. Скасування реєстрації не зупиняє вже запущений обробник. Використовуйте try/
finallyдля звичайного виходу або помилки, що обробляється; примусова зупинка також припиняє подальше опитування цього сценарію. - Невідоме непусте ім'я події під час реєстрації відхиляється із системним повідомленням. Порожнє ім'я нічого не робить. Наявність оброблювача перевіряється лише при спрацьовуванні; помилку в його імені краще виявити заздалегідь через SubExists та перевірку скрипту в IDE.
У C# обробник потрібно явно зареєструвати: RegisterRoutine("Handler", Handler). Зміни HP, мани та витривалості надходять через чергу native-подій; Death та SeeNewPlayer перевіряються за знімками локального світу. Прямі підписки з аргументами доступні через SubscribeEvent("UO.JournalEntry", handler) та аналогічні native-імена. Усі підписки звільняються після завершення або скасування цього виконання.
Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
RegisterRoutine("HealthChanged", () => UO.Print("HP changed"));
UO.SetEventProc("ChangeHitPoints", "HealthChanged");
await WaitAsync(5000);Параметри та порядок виконання:
- ChangeHitPoints спостерігає HP свого персонажа. OnHealthChanged - ім'я метод нижче/вище Main у тому ж завантаженому файлі. UO.Wait обслуговує події; порожній другий аргумент відключає повторення.
- Обробник тільки попереджає та не вибирає лікування автоматично. При зміні HP 60 → 50 → 70 виконуються дві реакції; це не лічильник ударів.
var registrationOnHealthChanged = RegisterRoutine("OnHealthChanged", OnHealthChanged);
UO.SetEventProc("ChangeHitPoints", "OnHealthChanged");
try
{
for (int tick = (int)(1); tick <= 40; tick += (int)(1))
{
UO.Wait(250);
}
}
finally
{
UO.SetEventProc("ChangeHitPoints", "");
}
void OnHealthChanged()
{
var hp = UO.HP();
if (Truth(hp < 40))
{
UO.Print("Low health: " + Convert.ToString(hp) + ". Check healing or retreat.");
}
else
{
UO.Print("Health changed: " + Convert.ToString(hp));
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- evChangeMana та ChangeMana — одна подія. Тут дві незалежні підписки та два різні обробники, а не два обробники на одне ім'я. Пороги 20 та 10 можна змінити.
- Очікування триває 5 секунд. Відновлення ресурсів теж виявляється, але if не видає попередження, коли значення вже вище за поріг.
return RunScenario();
object? RunScenario()
{
var registrationOnManaChanged = RegisterRoutine("OnManaChanged", OnManaChanged);
var registrationOnStaminaChanged = RegisterRoutine("OnStaminaChanged", OnStaminaChanged);
UO.SetEventProc("evChangeMana", "OnManaChanged");
UO.SetEventProc("ChangeStamina", "OnStaminaChanged");
try
{
for (int tick = (int)(1); tick <= 20; tick += (int)(1))
{
UO.Wait(250);
}
}
finally
{
UO.SetEventProc("ChangeMana", "");
UO.SetEventProc("ChangeStamina", "");
}
return null;
}
void OnManaChanged()
{
if (Truth(UO.Mana() < 20))
{
UO.Print("Mana below 20: postpone expensive spells");
}
}
void OnStaminaChanged()
{
if (Truth(UO.Stamina() < 10))
{
UO.Print("Stamina below 10: consider a movement break");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- SeeNewPlayer виявляє появу serial у завантаженому наборі mobiles, включаючи NPC. Одночасне завантаження п'яти істот не гарантує п'ять дзвінків.
- GetMobiles() — окреме читання актуального набору, не ID з події. Щоб вибрати ворога, потрібні очевидні умови; приклад навмисно нікого не атакує.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var registrationOnMobileAppeared = RegisterRoutine("OnMobileAppeared", OnMobileAppeared);
UO.SetEventProc("SeeNewPlayer", "OnMobileAppeared");
try
{
UO.Wait(5000);
}
finally
{
UO.SetEventProc("SeeNewPlayer", "");
}
UO.Wait(1000);
return null;
}
void OnMobileAppeared()
{
var mobiles = UO.GetMobiles();
UO.Print("Loaded mobiles now: " + Convert.ToString(ArrayLength(mobiles)));
}
int ArrayLength(object? value) => value is System.Array array ? array.Length : 0;
private IDisposable RegisterRoutine(string name, Action handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Action<string[]> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<string[], Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: eventname (Any), procname (Any)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(1). -
InjectionScript.Runtime.InjectionApiUO.SetEvent:SetEvent(arguments[0], InjectionValue.False). -
InjectionScript.Runtime.InjectionApiUO.SetEvent:SetEvent(arguments[0], InjectionValue.True, InjectionValue.True, arguments[1]).
Внутрішній код реалізації, не самостійний скрипт.
case "SetEventProc":
SetStateEvent([arguments[0], !string.IsNullOrWhiteSpace(Convert.ToString(arguments[1])), true, arguments[1]]);
return true;Внутрішній код реалізації, не самостійний скрипт.
case "seteventproc":
{
if (string.IsNullOrWhiteSpace(Text(1)))
SetEvent(arguments[0], InjectionValue.False);
else
SetEvent(arguments[0], InjectionValue.True, InjectionValue.True, arguments[1]);
return InjectionValue.Unit;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.SetPauseScriptOnDisconnectStatus(object? value);Змінює правило паузи скриптів у разі втрати з'єднання.
-
value— 0 вимикає; будь-яке ненульове ціле включає.
void - значення немає. Викликайте окремим рядком; завершення не підтверджує дію сервера.
- SetPauseScriptOnDisconnectStatus задає _manager.PauseScriptsOnDisconnect = enabled != 0. Вже запущені скрипти не отримують команду PauseResumeScript.
- Змінює налаштування клієнта. Значення не є результатом перевірки з'єднання та не підтверджує обробку сервером.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.
UO.Print("Calling UO.SetPauseScriptOnDisconnectStatus");
UO.SetPauseScriptOnDisconnectStatus(1);Параметри та порядок виконання:
- Змінює правило паузи скриптів у разі втрати з'єднання.
UO.SetPauseScriptOnDisconnectStatus(1);Параметри та порядок виконання:
- SetPauseScriptOnDisconnectStatus задає _manager.PauseScriptsOnDisconnect = enabled != 0. Вже запущені скрипти не отримують команду PauseResumeScript.
return RunScenario();
object? RunScenario()
{
UO.SetPauseScriptOnDisconnectStatus(0);
return null;
}Параметри та порядок виконання:
- Змінює налаштування клієнта. Значення не є результатом перевірки з'єднання та не підтверджує обробку сервером.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
ApplyMode(1);
return null;
}
void ApplyMode(dynamic mode)
{
UO.SetPauseScriptOnDisconnectStatus(mode);
}
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: value (Any)
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.SetPauseScriptOnDisconnectStatus:bridge.SetPauseScriptOnDisconnectStatus(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
case "setpausescriptondisconnectstatus": bridge.SetPauseScriptOnDisconnectStatus(Arg(0)); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.SetScriptName(object? scriptIndex, object? value);Змінює ім'я одного активного запуску. Допомагає розрізняти завдання в списку і через GetScriptName.
-
scriptIndex— Обов'язковий ScriptIndex — поточний індекс запуску: 0 позначає перший, далі 1, 2… Отримуйте його через GetScriptsList; це не serial, ім'я файлу і не результат StartScript. Негативний/відсутній індекс нічого не змінює. -
value— Обов'язковий Value — нове ім'я, яке перетворюється на рядок. Прогалини допустимі; порожній рядок також допустимий. Це підпис поточного запуску, а не нове ім'я файлу чи процедури у вихідному коді.
void — значення, що повертається, немає. Не порівнюйте дзвінок з true/1. Стан перевіряйте окремим читанням GetScriptState; результат такого читання - "0" (немає запуску), "1" (працює), "2" (пауза).
- Працює лише із запусками поточного сеансу. Відкрита вкладка без виконання не є активним запуском. Зупинка не видаляє вихідний файл і не вимикає з'єднання з сервером.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
for (int index = 0; index < UO.GetScriptsCount(); index++)
if (UO.GetScriptName(index) == "Worker")
{ UO.SetScriptName(index, "Worker renamed"); break; }Параметри та порядок виконання:
- MineOre шукається в активних запусках, Mining - новий підпис. Імена всередині лапок придумані користувачем і можуть бути замінені.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
var index = FindNamedRun("MineOre");
if (Truth(index >= 0))
{
UO.SetScriptName(index, "Mining");
}
dynamic FindNamedRun(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Замініть wantedPath своїм абсолютним шляхом. Змінюється підпис першого активного запуску файлу, а файл на диску залишається на попередньому місці.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return RunScenario();
object? RunScenario()
{
var wantedPath = "D:/Game/AutoLoad/Scripts/Worker.csx";
var index = FindFileRun(wantedPath);
if (Truth(index >= 0))
{
UO.SetScriptName(index, "Worker A");
}
return null;
}
dynamic FindFileRun(dynamic wantedPath)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(Convert.ToString(ReplaceText(UO.GetScriptPath(index), Chr(92), "/")) == Convert.ToString(ReplaceText(wantedPath, Chr(92), "/"))))
{
return index;
}
}
return -1;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string ReplaceText(object? value, object? oldValue, object? newValue) => (Convert.ToString(value) ?? "").Replace(Convert.ToString(oldValue) ?? "", Convert.ToString(newValue) ?? "");Параметри та порядок виконання:
- GetScriptState = 2 додає текст paused до імені. Це одноразовий підпис: він не оновлюється автоматично після продовження і не керує паузою.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var index = FindNamedRun("Mining");
if (Truth(index >= 0))
{
var newName = "Mining";
if (Truth(UO.GetScriptState(index) == 2))
{
newName = "Mining (paused)";
}
UO.SetScriptName(index, newName);
}
return null;
}
dynamic FindNamedRun(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptIndex (Any), value (Any)
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.SetScriptName:bridge.SetScriptName(Arg(0), Text(1)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(1).
Внутрішній код реалізації, не самостійний скрипт.
case "setscriptname": bridge.SetScriptName(Arg(0), Text(1)); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.StartScript(object? scriptPath);int: кількість активних запусків після прийнятого запуску; 65535 (0xFFFF) = помилка запуску. Це не індекс нового скрипта, не bool і не результат завершення.
- Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
- Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
- "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.StartScript("Scripts/Worker.csx");
UO.Print("StartScript: " + Convert.ToString(result));Параметри та порядок виконання:
- Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
- Перед прикладами окремо створіть зазначені файли Worker.csx. Помилковий/недоступний шлях, невідповідна Main, вимкнений C# або заборона паралельного запуску спричиняють відмову. Якщо попередній запуск ще зупиняється, можливий відкладений повтор; прийняття запуску не означає завершення. Короткий скрипт може завершитися ще до читання повернутої кількості.
- int: кількість активних запусків після прийнятого запуску; 65535 (0xFFFF) = помилка запуску. Це не індекс нового скрипта, не bool і не результат завершення.
- Обов'язковий ScriptPath - рядок. Відносний шлях починається у папці AutoLoad цього клієнта; абсолютний шлях припустимо. Шлях із пробілами укладайте у лапки. Потрібен .csx з кодом на верхньому рівні або звичайний .cs/.csproj з підтримуваною точкою входу C#.
var count = UO.StartScript("Scripts/Worker.csx");
if (Truth(count==65535))
{
UO.Print("launch failed");
}
else
{
UO.Print("Active executions: " + Convert.ToString(count));
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. UO.Wait(250), де він використовується, чекає 250 мілісекунд.
- Перед прикладами окремо створіть зазначені файли Worker.csx. Помилковий/недоступний шлях, невідповідна Main, вимкнений C# або заборона паралельного запуску спричиняють відмову. Якщо попередній запуск ще зупиняється, можливий відкладений повтор; прийняття запуску не означає завершення. Короткий скрипт може завершитися ще до читання повернутої кількості.
- int: кількість активних запусків після прийнятого запуску; 65535 (0xFFFF) = помилка запуску. Це не індекс нового скрипта, не bool і не результат завершення.
- Обов'язковий ScriptPath - рядок. Відносний шлях починається у папці AutoLoad цього клієнта; абсолютний шлях припустимо. Шлях із пробілами укладайте у лапки. Потрібен .csx з кодом на верхньому рівні або звичайний .cs/.csproj з підтримуваною точкою входу C#.
return RunScenario();
object? RunScenario()
{
var count = UO.StartScript("Scripts/My Worker.csx");
if (Truth(count != 65535))
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
UO.Print(Convert.ToString(index) + ": " + UO.GetScriptPath(index));
}
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Під Main наведено функцію повністю. Її параметри та результат пояснюються окремо від API-команди, яку вона викликає.
- TryStartCSharp порівнює результат з 65535 і повертає true/false. Вона не чекає завершення і не перетворює кількість на індекс.
- int: кількість активних запусків після прийнятого запуску; 65535 (0xFFFF) = помилка запуску. Це не індекс нового скрипта, не bool і не результат завершення.
- Обов'язковий ScriptPath - рядок. Відносний шлях починається у папці AutoLoad цього клієнта; абсолютний шлях припустимо. Шлях із пробілами укладайте у лапки. Потрібен .csx з кодом на верхньому рівні або звичайний .cs/.csproj з підтримуваною точкою входу C#.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
if (Truth(TryStartCSharp("Scripts/Worker.csx")))
{
UO.Print("launch accepted");
}
else
{
UO.Print("check file, Main and execution settings");
}
return null;
}
dynamic TryStartCSharp(dynamic fileName)
{
var count = UO.StartScript(fileName);
return Truth(count != 65535);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptPath (Any)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.StartScript:bridge.StartScript(Text(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0).
Внутрішній код реалізації, не самостійний скрипт.
case "startscript": return new InjectionValue(bridge.StartScript(Text(0)));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.StopAllScripts();Параметрів немає.
void — значення, що повертається, немає. Не порівнюйте дзвінок з true/1. Стан перевіряйте окремим читанням GetScriptState; результат такого читання - "0" (немає запуску), "1" (працює), "2" (пауза).
- Працює лише із запусками поточного сеансу. Відкрита вкладка без виконання не є активним запуском. Зупинка не видаляє вихідний файл і не вимикає з'єднання з сервером.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
- Аргументів немає. Скасуються виконувані та призупинені процедури, що очікують запуску запити та чергу повторних запусків. Скрипт, що викликає, теж отримує скасування: не поміщайте обов'язкове збереження/звіт після цієї команди. Інші профілі та процеси не торкаються.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.
UO.Print("Calling UO.StopAllScripts");
UO.StopAllScripts();Параметри та порядок виконання:
- У команди порожні дужки. Здійсніть потрібне збереження до дзвінка. Сам контролер теж буде зупинено.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
UO.StopAllScripts();Параметри та порядок виконання:
- Connected перевіряє вхід у світ, Dead – смерть. StopAllScripts викликається лише при виконанні обох умов; пример проверяет их один раз.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return RunScenario();
object? RunScenario()
{
if (Truth(UO.Connected()))
{
if (Truth(UO.Dead()))
{
UO.StopAllScripts();
}
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- 5000 — мілісекунди в UO.Wait, а не параметр StopAllScripts. Ручна чи автоматична пауза контролера може відкласти виконання; це незалежний таймер.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var delayMs = 5000;
UO.Wait(delayMs);
UO.StopAllScripts();
return null;
}
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.StopAllScripts:bridge.StopAllScripts().
Внутрішній код реалізації, не самостійний скрипт.
case "stopallscripts": bridge.StopAllScripts(); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.StopScript(object? scriptIndex);Запитує скасування одного активного запуску, у тому числі на паузі. Використовуйте, коли роботу цього запуску потрібно закінчити, а не продовжити пізніше.
-
scriptIndex— Обов'язковий ScriptIndex — поточний індекс запуску: 0 позначає перший, далі 1, 2… Отримуйте його через GetScriptsList; це не serial, ім'я файлу і не результат StartScript. Негативний/відсутній індекс нічого не змінює.
void — значення, що повертається, немає. Не порівнюйте дзвінок з true/1. Стан перевіряйте окремим читанням GetScriptState; результат такого читання - "0" (немає запуску), "1" (працює), "2" (пауза).
- Працює лише із запусками поточного сеансу. Відкрита вкладка без виконання не є активним запуском. Зупинка не видаляє вихідний файл і не вимикає з'єднання з сервером.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
- Скасування кооперативне: будить очікування паузи і перевіряється двигуном; вже надіслані дії серверу не скасовуються. Скасований запуск відразу виключається з активного списку, хоча звільнення ресурсів може тривати. Не перевіряйте завершення за попереднім індексом: під ним може бути інший запуск.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
for (int index = 0; index < UO.GetScriptsCount(); index++)
if (UO.GetScriptName(index) == "Worker")
{ UO.StopScript(index); break; }Параметри та порядок виконання:
- MineOre - ім'я запуску. -1 не передається в StopScript. Після зупинки збережений індекс більше не використовується.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
var index = FindNamedRun("MineOre");
if (Truth(index >= 0))
{
UO.StopScript(index);
}
dynamic FindNamedRun(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Код 2 вибирає зупинений запуск. StopScript завершує його, а не знімає паузу; інші завдання продовжуються.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return RunScenario();
object? RunScenario()
{
var index = FindNamedRun("MineOre");
if (Truth(index >= 0))
{
if (Truth(UO.GetScriptState(index) == 2))
{
UO.StopScript(index);
}
}
return null;
}
dynamic FindNamedRun(dynamic wanted)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(UO.GetScriptName(index) == wanted))
{
return index;
}
}
return -1;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Абсолютний шлях вибирає перший активний запуск файлу. Це не видалення файлу і не зупиняє всі процедури з цього файлу.
- Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var wantedPath = "D:/Game/AutoLoad/Scripts/Worker.csx";
var index = FindFileRun(wantedPath);
if (Truth(index >= 0))
{
UO.StopScript(index);
}
return null;
}
dynamic FindFileRun(dynamic wantedPath)
{
var indices = UO.GetScriptsList();
foreach (var index in indices)
{
if (Truth(Convert.ToString(ReplaceText(UO.GetScriptPath(index), Chr(92), "/")) == Convert.ToString(ReplaceText(wantedPath, Chr(92), "/"))))
{
return index;
}
}
return -1;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string ReplaceText(object? value, object? oldValue, object? newValue) => (Convert.ToString(value) ?? "").Replace(Convert.ToString(oldValue) ?? "", Convert.ToString(newValue) ?? "");
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: scriptIndex (Any)
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.StopScript:bridge.StopScript(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
case "stopscript": bridge.StopScript(Arg(0)); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.SubExists(object? subrutineName);Перевіряє, чи зареєстрований C#-делегат із зазначеним ім'ям у поточному виконанні. Це реєстр callback-функцій цієї сесії, без автоматичного пошуку довільних методів через reflection; явно завантажені файлові входи доступні за ключом.
-
subrutineName— рядкове ім’я, задане RegisterRoutine. Пробіли по краях видаляються; пошук зареєстрованого імені не залежить від регістру.
int: 1 — умова виконана, 0 — не виконано. Збережіть результат одного виклику, якщо він потрібний кількох перевірок.
- Реєстрація та завдання належать одному виконанню. Інший персонаж, профіль чи наступний запуск має власний реєстр.
- ?RegisterRoutine? приймає ?
Action?, ?Func<Task>? або делегат з масивом рядкових аргументів для ?Exec?. Видалення реєстрації не запускає код і унеможливлює подальший пошук імені. - Основний скрипт повинен залишатися активним, поки потрібні його помічники: після закінчення завдання скасовуються, а реєстрації та підписки звільняються.
- FunRunning не є індексом менеджера. GetScriptsList та GetScriptState описують самостійні запуски файлів; локальний callback окремого індексу не отримує.
- Помилка callback передається основному скрипту на наступній перевірці. WaitAsync, UO.Wait та інструментовані C#-цикли підтримують паузу, скасування та обробку черги подій.
Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
RegisterRoutine("Hello", () => UO.Print("Hello"));
UO.Print("Registered flag: " + UO.SubExists("Hello"));Параметри та порядок виконання:
- Команда повертає int: у C# перевіряйте result != 0 або result == 1; пряме порівняння з true неприпустимо. Визначення WeightWatch наведено нижче та реєструється через RegisterRoutine перед викликом команди.
- Збережіть приклад як окремий файл, завантажте його в IDE/менеджер і запускайте Main, щоб інші процедури потрапили до каталогу. WeightWatch/ManaWatch — повністю визначені тут навчальні процедури: три виміри ваги/мани з інтервалом UO.Wait(1000), тобто 1000 мс, висновок лише при вході у світ. Це не постійний моніторинг; пауза може розтягнути час. Для прикладу із двома завданнями має бути дозволено одночасний запуск процедур.
var registrationWeightWatch = RegisterRoutine("WeightWatch", WeightWatch);
if (Truth(Truth(UO.SubExists("WeightWatch")) == true))
{
UO.CallSub("WeightWatch");
}
while (UO.FunRunning("WeightWatch") != 0) await WaitAsync(25);
void WeightWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Weight: " + Convert.ToString(UO.Weight()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- WeightWatch може бути завантажений з іншого файлу. Якщо його немає, вибирається оголошений тут ManaWatch. Якщо основний знайдений, але не може запуститись, автоматичного переходу до запасного не буде.
- Збережіть приклад як окремий файл, завантажте його в IDE/менеджер і запускайте Main, щоб інші процедури потрапили до каталогу. WeightWatch/ManaWatch — повністю визначені тут навчальні процедури: три виміри ваги/мани з інтервалом UO.Wait(1000), тобто 1000 мс, висновок лише при вході у світ. Це не постійний моніторинг; пауза може розтягнути час. Для прикладу із двома завданнями має бути дозволено одночасний запуск процедур.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var registrationManaWatch = RegisterRoutine("ManaWatch", ManaWatch);
if (Truth(UO.SubExists("WeightWatch") == 1))
{
UO.CallSub("WeightWatch");
}
else if (Truth(UO.SubExists("ManaWatch")))
{
UO.CallSub("ManaWatch");
}
while (UO.FunRunning("ManaWatch") != 0)
await WaitAsync(25);
return null;
}
void ManaWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Mana: " + Convert.ToString(UO.Mana()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- HaveMonitors перевіряє два імені через &&. За відсутності хоча б одного Main не викликає жодного завдання. Перевіряється набір визначень, а не гарантія успішного одночасного запуску.
- Збережіть приклад як окремий файл, завантажте його в IDE/менеджер і запускайте Main, щоб інші процедури потрапили до каталогу. WeightWatch/ManaWatch — повністю визначені тут навчальні процедури: три виміри ваги/мани з інтервалом UO.Wait(1000), тобто 1000 мс, висновок лише при вході у світ. Це не постійний моніторинг; пауза може розтягнути час. Для прикладу із двома завданнями має бути дозволено одночасний запуск процедур.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var registrationWeightWatch = RegisterRoutine("WeightWatch", WeightWatch);
var registrationManaWatch = RegisterRoutine("ManaWatch", ManaWatch);
if (Truth(HaveMonitors()))
{
UO.CallSub("WeightWatch");
UO.CallSub("ManaWatch");
}
while (UO.FunRunning("WeightWatch") != 0 || UO.FunRunning("ManaWatch") != 0)
await WaitAsync(25);
return null;
}
dynamic HaveMonitors()
{
return UO.SubExists("WeightWatch") != 0 && UO.SubExists("ManaWatch") != 0;
}
void WeightWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Weight: " + Convert.ToString(UO.Weight()));
}
UO.Wait(1000);
}
}
void ManaWatch()
{
dynamic sample = 0;
for (sample = (int)(1); sample <= 3; sample += (int)(1))
{
if (Truth(UO.Connected()))
{
UO.Print("Mana: " + Convert.ToString(UO.Mana()));
}
UO.Wait(1000);
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
private IDisposable RegisterRoutine(string name, Action handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Action<string[]> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
private IDisposable RegisterRoutine(string name, Func<string[], Task> handler) => global::ClassicUO.CSharp.CSharpScriptContext.Current.RegisterRoutine(name, handler);
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: subrutineName (String)
Результат: int / Integer.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.SubExists. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.SubExists:bridge.SubExists(subrutineName).
Внутрішній код реалізації, не самостійний скрипт.
case "SubExists":
string requested = Convert.ToString(arguments[0]) ?? "";
result = Exists(requested) || events is ICSharpScriptHost known && known.HasCSharpScript(requested) ? 1 : 0;
return true;Внутрішній код реалізації, не самостійний скрипт.
public int SubExists(string subrutineName) => bridge.SubExists(subrutineName) ? 1 : 0;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.Terminate();
void UO.Terminate(object? subrutineName);-
subrutineName— Необов’язковий рядок. Без аргументу або з порожнім рядком вибирається останній запущений файл; "all" запитує скасування всіх запусків. Для файлів C# використовуйте точний ключ із каталогу, наприкладharvest.csx::Main. Довільне ім’я локального callback, наприкладHarvest, працює лише після його явної реєстрації черезRegisterRoutine. Сам файл має один вхідMain; окремі методи класу не стають автоматично окремими запускними процедурами.
void: команда не повертає число та не очікує завершення робочого потоку. Вона негайно вимагає скасування. Виконання припиняється на найближчій перевірці скасування; паузи, точки зупинки та вбудовані очікування перериваються. Серверні дії, які вже відправлені до скасування, не відкочуються.
Значення UO.FunRunning(name) == 0 також можливе одразу після запиту скасування. Воно не означає, що блок finally попереднього callback уже завершився. Повторний CallSub або Exec того самого локального імені пропускається, поки попередній обробник фактично не завершить роботу.
- UO.Terminate() вибирає процедуру по порядку запуску, а не по імені, рядку редактора, часу останньої дії або порядку відображення. Поставлена на паузу процедура також вважається запущеною.
- Очищається локальний приціл, що належить цьому запуску, і скасовується автоматичний маршрут, що залишився. Скасування руху виконується на ігровому потоці; якщо маршрут вже замінено іншим запуском або користувачем, колишній власник його не зупиняє. Надіслані серверу кроки не відгукуються.
- Команда залишається доступною при увімкненому налаштуванні одного одночасного запуску. Скасована процедура звільняє місце лише після очищення свого робочого потоку; раніше новий запуск пропускається.
- При зупинці на ім'я також скасовуються відповідні відкладені запуски. Завершені процедури не змінюються. Про відсутність відповідного запуску клієнт повідомляє статус. Виклик стороннього нативного плагіна, який не підтримує скасування, не можна безпечно перервати примусовим знищенням потоку.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Для файлів C# використовуйте точний ключ із каталогу, наприклад harvest.csx::Main. Довільне ім’я локального callback, наприклад Harvest, працює лише після його явної реєстрації через RegisterRoutine. Сам файл має один вхід Main; окремі методи класу не стають автоматично окремими запускними процедурами.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
UO.Terminate("harvest.csx::Main");
UO.Print("Cancellation requested for harvest.csx::Main");Приклад запитує скасування вже запущеного harvest.csx::Main. Повідомлення не підтверджує завершення його finally або відкат ігрових дій.
var procedureName = "harvest.csx::Main";
UO.Terminate(procedureName);
UO.Print("Cancellation requested for harvest.csx::Main");Точний ключ harvest.csx::Main відрізняється від heal.csx::Main. Замініть демонстраційний ключ на ключ свого завантаженого файлу; довільні суфікси на кшталт #2 не створюють другого входу.
return RunScenario();
object? RunScenario()
{
var procedureKey = "harvest.csx::Main";
UO.Terminate(procedureKey);
UO.Print("Cancellation requested: " + procedureKey);
return null;
}Рядок terminate harvest.csx::Main передає той самий ключ через UO.Exec. Ключ із пробілами потрібно взяти в лапки всередині командного рядка.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var command = "terminate harvest.csx::Main";
UO.Exec(command);
UO.Print("Stop command sent");
return null;
}
}Параметри та порядок виконання:
- Форма без аргументів вибирає останній запущений скрипт, включаючи поставлений паузу. Це політика прикладу, а чи не обов'язкова реакція низьке здоров'я; повідомлення виводиться до запиту скасування.
if (UO.GetHP() <= 30)
{
UO.Print("Low health: requesting cancellation of the most recent run");
UO.Terminate();
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.Terminate. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Terminate:bridge.Terminate(string.Empty).
Внутрішній код реалізації, не самостійний скрипт.
public void Terminate() => bridge.Terminate(string.Empty);Параметри: subrutineName (String)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpCallbacks.TryInvoke. -
InjectionScript.Runtime.InjectionApiUO.Terminate. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Terminate:bridge.Terminate(subrutineName).
Внутрішній код реалізації, не самостійний скрипт.
case "Terminate" when arguments.Length == 1:
string routine = Convert.ToString(arguments[0]) ?? "";
if (Exists(routine)) { Cancel(routine); return true; }
if (Cancel(routine)) return true;
return false;Внутрішній код реалізації, не самостійний скрипт.
public void Terminate(string subrutineName) => bridge.Terminate(subrutineName);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.TerminateAll();Параметрів немає.
void: немає результату. Команда запитує скасування всіх поточних запусків і повертає управління коду, що викликає, якщо він сам не був скасований. Очищення робочих потоків здійснюється після спрацювання їх перевірок скасування.
- Точний синтаксис - UO.TerminateAll(), без пробілу всередині імені та без аргументів. UO.Terminate("all") підтримується як сумісний альтернативний запис.
- Зупиняються працюючі процедури, процедури на ручній паузі та на точці зупинки, вбудовані очікування та зареєстровані відкладені запуски. Повторний дзвінок за відсутності роботи безпечний.
- Зняття локальних прицілів та автоматичних маршрутів враховує їх власників. маршрут зупиненого скрипта, що залишився, скасовується на ігровому потоці; новий маршрут користувача, який його замінив, зберігається. Вже надіслані пакети руху не скасовуються.
- Скасування не відкочує вже надіслані серверу дії. Код сторонніх нативних плагінів без підтримки скасування не можна безпечно знищити разом із потоком. Нові явні запуски після виконання команди дозволені; при включеній галочці вони чекають на звільнення місця в тому сенсі, що спроба до завершення очищення пропускається, а не ставиться в чергу.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.
UO.Print("Calling UO.TerminateAll");
UO.TerminateAll();Параметри та порядок виконання:
- TerminateAll немає параметрів. Умова UO.Dead() перевіряє смерть персонажа перед черговою ітерацією.
- Під час виконання умови скасовуються і поточний Main, та інші запуски C#. Повідомлення Print розташоване до зупинки, оскільки після неї код цієї процедури припиняється.
- WaitAsync(250) задає паузу 250 мілісекунд між перевірками у цьому прикладі. Команда зупинки не змінює тривалість звичайних пауз скрипту.
for (int cycle = (int)(1); cycle <= 10; cycle += (int)(1))
{
if (Truth(UO.Dead()))
{
UO.Print("Character is dead: stopping all C# scripts");
UO.TerminateAll();
}
await Delay(250);
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- У цьому альтернативному записі використовується UO.Terminate з одним параметром subrutineName="all". Це еквівалент UO.TerminateAll().
- Рядок all – спеціальне значення, а не ім'я процедури, яке потрібно оголосити. Скасується і EmergencyStop.
- Для аварійної ігрової клавіші використовуйте однорядкову команду з першого прикладу: окрема процедура EmergencyStop сама підпорядковується забороні паралельних запусків.
return RunScenario();
object? RunScenario()
{
UO.Print("Stopping all C# scripts");
UO.Terminate("all");
return null;
}Параметри та порядок виконання:
- GetSerial зберігає serial обов'язкового об'єкта, тут власного рюкзака. Exists=0 означає, що цей об'єкт зараз невідомий клієнту.
- TerminateAll викликається без аргументів лише при порушенні вибраної умови. Ця політика зупиняє всі процедури, а не лише роботу з цим рюкзаком.
- Спочатку виводиться причина зупинки. Після запиту скасування поточна процедура також припиняється; розраховувати виконання наступного дії не можна.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var bag = UO.GetSerial("backpack");
if (Truth(UO.Exists(bag) == 0))
{
UO.Print("Required backpack is unavailable: stopping all scripts");
UO.TerminateAll();
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}Параметри та порядок виконання:
- За відсутності з'єднання вибирається зупинка всіх запусків. Команда не повертає кількість скасованих скриптів і скасовує поточний запуск.
if (UO.Connected() == 0)
{
UO.Print("Disconnected: requesting cancellation of every active script");
UO.TerminateAll();
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: void / Unit.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.TerminateAll. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.Terminate:bridge.Terminate("all").
Внутрішній код реалізації, не самостійний скрипт.
public void TerminateAll() => bridge.Terminate("all");Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.Time();Читає місцеву добу комп'ютера числом HHMMSS. Зручна для вибору дозволеного часу, не для вимірювання тривалості.
Параметрів немає.
int HHMMSS, 0..235959 з допустимими хвилинами та секундами. 07:29:35 -> 72935; опівночі -> 0. Нуль - допустимий час, а не помилка і не логічний прапор false.
- Параметрів немає, форм із аргументами немає. Порожні дужки лише читають час: виклик не чекає, не запускає таймер та не відправляє пакети у гру.
- RealTimeSource.Now читає DateTime.Now: місцеву дату/час комп'ютера, не UTC, не час шарду та не ігровий годинник. Часовий пояс, літній час та ручний переведення годинника впливають на результат. Кожен дзвінок фіксує окремий момент.
- Початкові нулі не зберігаються, мілісекунд немає. Чисельно ?13:00:00? мінус ?12:59:59? дає ?4041?, хоча пройшла одна секунда. Опівночі значення знову стає нулем.
- Не віднімайте календарні коди для розрахунку затримки. Використовуйте Timer() та дві позначки одного запуску. Календарний годинник може перевестися назад.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.Time();
UO.Print("Time: " + Convert.ToString(result));Параметри та порядок виконання:
- stamp читається один раз, щоб не змішати різні секунди. Int(stamp/10000) - годинник; Int(stamp/100) MOD 100 - хвилини; MOD 100 - секунди. Простий рядок не доповнює поля нулями.
var stamp = UO.Time();
var hour = stamp / 10000;
var minute = stamp / 100 % 100;
var second = stamp % 100;
UO.Print(Convert.ToString(hour) + ":" + Convert.ToString(minute) + ":" + Convert.ToString(second));Параметри та порядок виконання:
- 180000 - 18:00:00 включно; 220000 — 22:00:00 не включно. Одна перевірка вирішує, чи продовжувати Main. Розклад не реєструється, серія автоматично не запускається.
return RunScenario();
object? RunScenario()
{
var stamp = UO.Time();
if (Truth(stamp >= 180000) && Truth(stamp < 220000))
{
UO.Print("Evening batch permitted by local schedule");
}
else
{
UO.Print("Outside the local schedule");
return null;
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- ClockInWindow(stamp,first,last) приймає допустимі HHMMSS. 230000..20000 означає від 23:00 включно до 02:00 не включно: OR враховує північ. Рівні межі означають пустий інтервал. У тихий період Main завершується; функцію наведено цілком.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
if (Truth(ClockInWindow(UO.Time(), 230000, 20000)))
{
UO.Print("Local quiet period; do not start a new batch");
return null;
}
UO.Print("Outside the local quiet period");
return null;
}
dynamic ClockInWindow(dynamic stamp, dynamic first, dynamic last)
{
if (Truth(first == last))
{
return false;
}
if (Truth(first < last))
{
return Truth(stamp >= first) && Truth(stamp < last);
}
return Truth(stamp >= first) || Truth(stamp < last);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: int / Integer.
Під час виклику:
Внутрішній код реалізації, не самостійний скрипт.
public int Time()
{
var now = timeSource.Now;
return now.Hour * 10000 + now.Minute * 100 + now.Second;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.Timer();Читає час роботи поточного runtime в десятих частках секунди. Підходить для власних затримок та позначок дій.
Параметрів немає.
int 0..2147483647; одиниця - 100 мс. При 399 мс повернеться 3. Це показує годинник, а не true/false і не залишок перезаряджання.
- Параметрів немає, форм із аргументами немає. Порожні дужки лише читають час: виклик не чекає, не запускає таймер та не відправляє пакети у гру.
- Початок відліку належить цьому екземпляру runtime. Нова запущена процедура може отримати новий годинник; не можна порівнювати значення різних запусків або зберігати їх як абсолютну дату. Під час UO.Wait та паузи скрипту реальний час продовжує йти.
- Дробна частина десятих відкидається. Приблизно через 2485.5 діб число досягає 2147483647 і залишається таким, не переповнюючись.
- Це ваша затримка, а не серверна перезарядка навички/заклинання та не підтвердження успіху. Команда не дозволяє обходити обмеження сервера на рух, заклинання чи скрипти.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.Timer();
UO.Print("Timer: " + Convert.ToString(result));Параметри та порядок виконання:
- WaitAsync(250) запитує 250 мс; фактична затримка може бути більшою. Різниця двох позначок поділяється на 10.0 для отримання секунд. Крок показань UO.Timer - 100 мс.
var started = UO.Timer();
await Delay(250);
var elapsed = UO.Timer() - started;
var seconds = elapsed / 10.0;
UO.Print("Elapsed seconds: " + Convert.ToString(seconds));
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));Параметри та порядок виконання:
- Межа 30 задана в одиницях цієї функції. UO.Wait(50) звільняє виконання між перевірками. UO.Targeting читає наявність прицілу; приклад не кастує і вибирає мету. Якщо приціл з'явився, цикл закінчується.
- Додаткова перевірка верхньої межі завершує очікування навіть при лічильнику, що зупинився на межі int. Статус прицілу читається повторно та може змінитися між читаннями.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var started = UO.Timer();
while (Truth(UO.Timer() - started < 30) && !(Truth(UO.Targeting())))
{
if (Truth(UO.Timer() >= 2147483647))
{
break;
}
await Delay(50);
}
if (Truth(UO.Targeting()))
{
UO.Print("Target cursor available");
}
else
{
UO.Print("Target wait ended");
}
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- IntervalPassed(started,current,interval) повністю визначена під Main. interval=5 — половина секунди в одиницях цього годинника. Негативний інтервал, зворотний хід та int на верхньому кордоні дають false; точне досягнення інтервалу дає true.
- Це ваша затримка, а не серверна перезарядка навички/заклинання та не підтвердження успіху. Команда не дозволяє обходити обмеження сервера на рух, заклинання чи скрипти.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
async public Task<object?> RunScenarioAsync()
{
var started = UO.Timer();
await Delay(500);
var ready = IntervalPassed(started, UO.Timer(), 5);
if (Truth(ready))
{
UO.Print("Local retry interval passed");
}
return null;
}
dynamic IntervalPassed(dynamic started, dynamic current, dynamic interval)
{
if (Truth(interval < 0) || Truth(current < started))
{
return false;
}
if (Truth(current >= 2147483647))
{
return false;
}
return current - started >= interval;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: int / Integer.
Під час виклику:
Внутрішній код реалізації, не самостійний скрипт.
public int Timer() => (int)Math.Max(0d, Math.Min(int.MaxValue, timeSource.SinceStart.TotalMilliseconds / 100d));Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.Wait(object? waitTimeMS);Зупиняє поточний скрипт на задану кількість мілісекунд. Корисно між повторними перевірками стану, щоб скрипт не крутив безперервний цикл.
-
waitTimeMS— Цілі години в мілісекундах: 1000 = одна секунда. Використовуйте 0..2147483647. Це не кількість кроків, не секунди і не тримають підтвердження сервера.
void - результату немає. Викликайте окремим рядком. Закінчення затримки не означає, що предмет перемістився, завершення заклинання або з'єднання встановлено: потрібний стан перевіряйте окремо.
- Нуль не створює реальної затримки та не підходить як пауза у швидкому циклі. Негативний час не означає нескінченність: UO.Wait зводить його до 0; UO.Wait/sleep можуть відхилити його при активному callback, а в клієнтському мосту без них воно не чекає. Для скрипта, що переноситься, використовуйте тільки невід'ємний час.
UO.Wait(100);
// For an asynchronous script, use the host helper:
await WaitAsync(100);Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.
UO.Print("Calling UO.Wait");
UO.Wait(250);Параметри та порядок виконання:
- 250 - чверть секунди. Наступний рядок виконується після очікування; повідомлення Delay complete — текст прикладу, а чи не повернутий результат.
UO.Wait(250);
UO.Print("Delay complete");Параметри та порядок виконання:
- WaitForOnline повністю оголошено у цьому скрипті. Аргумент 20 означає максимум двадцять пауз по 250 мс. З'єднання перевіряється перед паузами та ще раз після останньої. Помічник повертає стан Connected (1/0); сама команда очікування нічого не повертає та не підключається до сервера.
return RunScenario();
object? RunScenario()
{
return WaitForOnline(20);
return null;
}
dynamic WaitForOnline(dynamic checks)
{
while (Truth(checks > 0))
{
if (Truth(UO.Connected()))
{
return 1;
}
UO.Wait(250);
checks = checks - 1;
}
return UO.Connected();
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Цикл робить рівно три читання ваги. Між читаннями є дві паузи по 500 мс, після останньої паузи немає. Повідомлення друкується при першому читанні та зміні ваги. Змінна previous зберігає порівнюване значення, а не налаштовує ігрову вагу.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var previous = -1;
var checks = 0;
while (Truth(checks < 3))
{
var weight = UO.Weight();
if (Truth(weight != previous))
{
UO.Print("Weight: " + Convert.ToString(weight));
previous = weight;
}
checks = checks + 1;
if (Truth(checks < 3))
{
UO.Wait(500);
}
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: waitTimeMS (Any)
Результат: void / Unit.
Під час виклику:
-
ClassicUO.CSharp.CSharpScriptGlobals.WaitAsync. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.WaitWithEvents:WaitWithEvents(Arg(0)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0).
Внутрішній код реалізації, не самостійний скрипт.
public async Task WaitAsync(int milliseconds)
{
ArgumentOutOfRangeException.ThrowIfNegative(milliseconds);
Checkpoint();
// Short slices allow Pause to suspend further script progress promptly.
int remaining = milliseconds;
while (remaining > 0)
{
int slice = Math.Min(remaining, 25);
await Task.Delay(slice, Cancellation).ConfigureAwait(false);
Checkpoint(); remaining -= slice;
}
}Внутрішній код реалізації, не самостійний скрипт.
case "wait": WaitWithEvents(Arg(0)); return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
int UO.Waiting();Перевіряє, чи залишилися підготовлені відповіді у черзі target.
Параметрів немає.
int 1 — є невідмінна відкладена мета об'єкта, тайла або скасування наступного прицілу; 0 - черга порожня. Не наявність відкритого курсора; для курсору використовуйте TargetPresent/Targeting.
Результат команди — числовий прапор: 1 означає виконану умову, 0 — невиконану. Після var result = команда (...) перевіряйте if (result != 0) або if (result == 0). Збережіть результат одного виклику: повторний виклик може виконати дію знову або прочитати стан, що вже змінився.
- Читається черга всього клієнта. Якщо одночасно працюють кілька процедур, враховуються відповіді кожної з них.
- Нуль означає лише відсутність очікуваної відповіді. Він не підтверджує успішне застосування навички або заклинання на сервері.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.Waiting();
UO.Print("Waiting: " + Convert.ToString(result));Параметри та порядок виконання:
- Після WaitTargetSelf і до серверного target очікується 1.
- CancelWaitTarget прибирає чергу; наступна перевірка дасть 0.
UO.WaitTargetSelf();
UO.Print(Convert.ToString(UO.Waiting()));
UO.CancelWaitTarget();Параметри та порядок виконання:
- Параметрів перевірки немає. UO.Wait=50 мс, максимум 20 очікувань.
- При відповіді, що залишилася, він скасовується. Перевірку результату серверної дії додайте окремо.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
var attempts = 0;
while (Truth(UO.Waiting()) && Truth(attempts < 20))
{
await Delay(50);
attempts = attempts + 1;
}
if (Truth(UO.Waiting()))
{
UO.CancelWaitTarget();
}
return null;
}
Task Delay(object? milliseconds) => WaitAsync(checked((int)Convert.ToDouble(milliseconds)));
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Параметри та порядок виконання:
- Перший рядок показує відкладені відповіді, другий стан прицілу.
- Можлива черга без курсору та курсор без черги; ці значення не взаємозамінні.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
UO.Print("Queued: " + Convert.ToString(UO.Waiting()));
UO.Print("Cursor: " + Convert.ToString(UO.TargetPresent()));
return null;
}
}C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.
Параметри: Немає параметрів.
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApiUO.Waiting. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.GetWaitTargetQueue:bridge.GetWaitTargetQueue().
Внутрішній код реалізації, не самостійний скрипт.
public int Waiting() => bridge.GetWaitTargetQueue().Length > 0 ? 1 : 0;ClassicUO — Bad Newbie & C# Scripts IDE