Skip to content

UO Topic scripts runtime

Codex edited this page Oct 12, 2026 · 6 revisions

Українська · Русский · 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

Приклади на тему

Нижче наведено короткі приклади. У повному описі кожної команди є параметри, результат, обмеження та кілька самостійних скриптів: прямий код, варіант із функцією та варіант із класом.

UO.GetScriptsList

Параметри, результат та всі сценарії

var indices = UO.GetScriptsList();
foreach (var index in indices)
{
    UO.Print(Convert.ToString(index) + ": " + UO.GetScriptName(index));
}

UO.TerminateAll

Параметри, результат та всі сценарії

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.CallSub

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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#-файли

Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .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);

1. Запустити спостерігача і продовжити Main - прямий скрипт

Параметри та порядок виконання:

  • 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;

2. Не перезапускати активне чи призупинене завдання — функція сценарію

Параметри та порядок виконання:

  • 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;

3. Два незалежні спостерігачі — клас сценарію

Параметри та порядок виконання:

  • Перший 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.

UO.CallSub(subrutineName) — UO.CallSub(String)

Параметри: subrutineName (String)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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);

UO.Date

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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() та дві позначки одного запуску. Календарний годинник може перевестися назад.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.Date();
UO.Print("Date: " + Convert.ToString(result));

1. Назвати денну серію збору ресурсів – прямий скрипт

Параметри та порядок виконання:

  • Результат дзвінка без настройок зберігається один раз. sessionLabel - рядок на зразок harvest-260930. Print тільки показує назву: файл не створюється, збирання ресурсів не запускається.
var dateStamp = UO.Date();
var sessionLabel = "harvest-" + Convert.ToString(dateStamp);
UO.Print(sessionLabel);

2. Завершити серію при зміні місцевого дня – функція сценарію

Параметри та порядок виконання:

  • 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;

3. Виділити рік, місяць і день – клас сценарію

Параметри та порядок виконання:

  • 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.

UO.Date() — UO.Date()

Параметри: Немає параметрів.

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

public int Date()

        {

            var now = timeSource.Now;

            return (now.Year % 100) * 10000 + now.Month * 100 + now.Day;

        }

UO.Exec

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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#-файли

Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .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);

1. Використовувати обрану навичку - прямий скрипт

Параметри та порядок виконання:

  • Hiding - єдиний аргумент "UseSkill". При вході у світ клієнт надсилає запит використання навички; успіх приховування визначає сервер. Та ж операція прямим викликом: UO.UseSkill("Hiding").
UO.Exec("useskill Hiding");

2. Надіслати рядкову мітку локальній процедурі — функція сценарію

Параметри та порядок виконання:

  • 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);
}

3. Запустити окремого спостерігача – клас сценарію

Параметри та порядок виконання:

  • Запускайте цей 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);
}

4. Завантажити скрипт із папки з пробілами — прямий скрипт

Параметри та порядок виконання:

  • Замініть шлях існуючим C#-файлом зі своєю процедурою Main. startscript завантажує файл та запитує запуск Main. Лапки належать текстовій команді; зворотні сліші шляхи зберігаються. Помилки запуску дивіться в IDE, оскільки Exec не повертає підтвердження.
UO.Exec("startscript 'C:\\UO Scripts\\Gather.csx'");

Реалізація команди

C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.

UO.Exec(parameters) — UO.Exec(String)

Параметри: parameters (String)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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);
        }

UO.FunRunning

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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#-файли

Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .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);

1. Запустити зареєстрований спостерігач без накладання – прямий скрипт

Параметри та порядок виконання:

  • Спочатку 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);
    }
}

2. Дочекатися завершення та прочитати результат фонової роботи – функція сценарію

Параметри та порядок виконання:

  • 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;
}

3. Скасувати зареєстрований async-помічник – клас сценарію

Параметри та порядок виконання:

  • 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.

UO.FunRunning(subrutineName) — UO.FunRunning(String)

Параметри: subrutineName (String)

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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;

UO.GetPauseScriptOnDisconnectStatus

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

dynamic UO.GetPauseScriptOnDisconnectStatus();

Читає налаштування паузи скриптів при вимкненні менеджера.

Параметри

Параметрів немає.

Повернене значення

int 1 — PauseScriptsOnDisconnect включений; 0 — вимкнено.

Поведінка

  • Читає прапор менеджера, що не поточну паузу окремого скрипта. Сам виклик не ставить та не знімає паузу.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

object? result = UO.GetPauseScriptOnDisconnectStatus();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));

1. Прочитати налаштування — прямий скрипт

Параметри та порядок виконання:

  • Значення визначає налаштування менеджера.
var enabled = UO.GetPauseScriptOnDisconnectStatus();
UO.Print(Convert.ToString(enabled));

2. Окремо перевірити з'єднання – функція сценарію

Параметри та порядок виконання:

  • Прапор налаштування та з'єднання читаються незалежно.
return  RunScenario();
 object? RunScenario()
{
    var pauseOnDisconnect = UO.GetPauseScriptOnDisconnectStatus();
    var online = UO.Connected();
    UO.Print(Convert.ToString(pauseOnDisconnect) + " " + Convert.ToString(online));
    return null;
}

3. Зберегти значення – клас сценарію

Параметри та порядок виконання:

  • Змінна містить знімок налаштування на момент читання.
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.

UO.GetPauseScriptOnDisconnectStatus() — UO.GetPauseScriptOnDisconnectStatus()

Параметри: Немає параметрів.

Результат: dynamic / Any.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "getpausescriptondisconnectstatus": return new InjectionValue(bridge.GetPauseScriptOnDisconnectStatus());

UO.GetScriptName

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

string UO.GetScriptName(object? scriptIndex);

Читає відображене ім'я активного запуску.

Параметри

  • scriptIndex — Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.

Повернене значення

string: отображаемое имя либо "", если индекса нет. У існуючого запуску ім'я також може бути явно встановлено в порожній рядок.

Поведінка

  • Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
  • Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
  • "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
  • ScriptIndex=0 — перший поточний запуск, який не обов'язково викликає скрипт. SetScriptName змінює ім'я, що відображається, не перейменовуючи файл.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.GetScriptName(0);
UO.Print("GetScriptName: " + Convert.ToString(result));

1. Перший виклик і результат – прямий скрипт

Параметри та порядок виконання:

  • Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
  • ScriptIndex=0 — перший поточний запуск, який не обов'язково викликає скрипт. SetScriptName змінює ім'я, що відображається, не перейменовуючи файл.
  • string: отображаемое имя либо "", если индекса нет. У існуючого запуску ім'я також може бути явно встановлено в порожній рядок.
  • Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.
var index = 0;
var name = UO.GetScriptName(index);
UO.Print(name);

2. Використання в циклі чи умові – функція сценарію

Параметри та порядок виконання:

  • Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. 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;
}

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Під 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.

UO.GetScriptName(scriptIndex) — UO.GetScriptName(Any)

Параметри: scriptIndex (Any)

Результат: string / String.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "getscriptname": return new InjectionValue(bridge.GetScriptName(Arg(0)));

UO.GetScriptPath

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

string UO.GetScriptPath(object? scriptIndex);

Читає шлях вихідного файлу активного запуску.

Параметри

  • scriptIndex — Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.

Повернене значення

string: збережений шлях вихідного файлу чи " " , якщо індексу немає. При запуску файлу зазвичай повний шлях; у команди або вихідного файлу в пам'яті звичайного файлу може не бути.

Поведінка

  • Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
  • Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
  • "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
  • ScriptIndex=0 вибирає перший поточний запуск. Результат указує його вихідник; команда не відкриває, не зберігає та не запускає цей файл.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.GetScriptPath(0);
UO.Print("GetScriptPath: " + Convert.ToString(result));

1. Перший виклик і результат – прямий скрипт

Параметри та порядок виконання:

  • Запускайте наведений 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;

2. Використання в циклі чи умові – функція сценарію

Параметри та порядок виконання:

  • Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. 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;
}

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Під 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.

UO.GetScriptPath(scriptIndex) — UO.GetScriptPath(Any)

Параметри: scriptIndex (Any)

Результат: string / String.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "getscriptpath": return new InjectionValue(bridge.GetScriptPath(Arg(0)));

UO.GetScriptState

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

int UO.GetScriptState(object? scriptIndex);

Читає стан виконання за індексом.

Параметри

  • scriptIndex — Обов'язковий ScriptIndex — ціле число, індекс з нуля зі свіжого GetScriptsList. Для негативного або відсутнього індексу повертається описаний порожній/невідомий результат. Не передавайте serial предмета, ім'я процедури або ID запуску з IDE.

Повернене значення

int — код стану: 0 = ні/невідомо, 1 = виконується, 2 = пауза. Це не bool: явно порівнюйте з 1 або 2.

Поведінка

  • Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
  • Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
  • "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
  • Враховується ручна/налагоджувальна пауза та налаштована пауза при вимкненні. Стан 1 не гарантує, що скрипт прямо зараз витрачає процесор або отримує дані сервера.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.GetScriptState(0);
UO.Print("GetScriptState: " + Convert.ToString(result));

1. Перший виклик і результат – прямий скрипт

Параметри та порядок виконання:

  • Запускайте наведений 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);

2. Використання в циклі чи умові – функція сценарію

Параметри та порядок виконання:

  • Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. 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;

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Під 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.

UO.GetScriptState(scriptIndex) — UO.GetScriptState(Any)

Параметри: scriptIndex (Any)

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "getscriptstate": return new InjectionValue(bridge.GetScriptState(Arg(0)));

UO.GetScriptsCount

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

int UO.GetScriptsCount();

Вважає активні запуски у цьому клієнті.

Параметри

Параметрів немає.

Повернене значення

int >= 0: кількість активних запусків, включаючи призупинені. Ця кількість, а не bool і не індекс скрипту.

Поведінка

  • Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
  • Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
  • "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
  • Аргументів немає. Підрахунок не сортує список та не змінює стан запусків.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.GetScriptsCount();
UO.Print("GetScriptsCount: " + Convert.ToString(result));

1. Перший виклик і результат – прямий скрипт

Параметри та порядок виконання:

  • Запускайте наведений C#-скрипт. Число 0, де воно передано, позначає індекс; порожні дужки означають відсутність аргументів. Текст Print – лише повідомлення прикладу.
  • Аргументів немає. Підрахунок не сортує список та не змінює стан запусків.
  • int >= 0: кількість активних запусків, включаючи призупинені. Ця кількість, а не bool і не індекс скрипту.
var count = UO.GetScriptsCount();
UO.Print(Convert.ToString(count));

2. Використання в циклі чи умові – функція сценарію

Параметри та порядок виконання:

  • Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. 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)));

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Під 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.

UO.GetScriptsCount() — UO.GetScriptsCount()

Параметри: Немає параметрів.

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "getscriptscount": return new InjectionValue(bridge.GetScriptsCount());

UO.GetScriptsList

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

dynamic UO.GetScriptsList();

Повертає поточні числові індекси скриптів.

Параметри

Параметрів немає.

Повернене значення

Array з int: індекси 0..N-1 або порожній масив. Елементи – числа, а не імена та не текстові записи.

Поведінка

  • Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
  • Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
  • "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.
  • Аргументів немає. Кожне число передавайте у відповідний getter імені, шляху чи стану. Отриманий масив – окремий знімок; його зміна не керує скриптами.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

object? result = UO.GetScriptsList();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));

1. Перший виклик і результат – прямий скрипт

Параметри та порядок виконання:

  • Запускайте наведений 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));
}

2. Використання в циклі чи умові – функція сценарію

Параметри та порядок виконання:

  • Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. 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;

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Під 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.

UO.GetScriptsList() — UO.GetScriptsList()

Параметри: Немає параметрів.

Результат: dynamic / Array.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "getscriptslist": return new InjectionValue(bridge.GetScriptsList().Select(value => new InjectionValue(value)).ToArray());

UO.Launch

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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 після звільнення запиту; сама запущена програма продовжує працювати.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.Launch("loot-report.txt");
UO.Print("Launch: " + Convert.ToString(result));

1. Відкрити готовий звіт про видобуток — прямий скрипт

Параметри та порядок виконання:

  • Покладіть існуючий loot-report.txt поряд зі скриптом. ОС відкриває його програмою, призначеною для .txt. Main повертає результат запиту Launch, а не вміст звіту та не підтвердження його прочитання.
var started = UO.Launch("loot-report.txt");
return started;

2. Передати редактору шлях із пробілами – функція сценарію

Параметри та порядок виконання:

  • Папка та звіт повинні існувати; замініть їх своїми. 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();

3. Підготувати список локальних журналів без вікна консолі – клас сценарію

Параметри та порядок виконання:

  • Приклад 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.

UO.Launch(file) — UO.Launch(Any)

Параметри: file (Any)

Результат: int / Integer.

Під час виклику:

Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.

Внутрішній код реалізації, не самостійний скрипт.

values => new InjectionValue(CompactLaunch(values))

UO.Launch(file, parameters) — UO.Launch(Any,Any)

Параметри: file (Any), parameters (Any)

Результат: int / Integer.

Під час виклику:

Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.

Внутрішній код реалізації, не самостійний скрипт.

values => new InjectionValue(CompactLaunch(values))

UO.Launch(file, parameters, workingDirectory) — UO.Launch(Any,Any,Any)

Параметри: file (Any), parameters (Any), workingDirectory (Any)

Результат: int / Integer.

Під час виклику:

Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.

Внутрішній код реалізації, не самостійний скрипт.

values => new InjectionValue(CompactLaunch(values))

UO.Launch(file, parameters, workingDirectory, hidden) — UO.Launch(Any,Any,Any,Any)

Параметри: file (Any), parameters (Any), workingDirectory (Any), hidden (Any)

Результат: int / Integer.

Під час виклику:

Виклик виконує збережений delegate обробника. Метод реєстрації створює цей delegate під час побудови API.

Внутрішній код реалізації, не самостійний скрипт.

values => new InjectionValue(CompactLaunch(values))

UO.PauseResumeScript

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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/менеджера або іншого скрипту.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

for (int index = 0; index < UO.GetScriptsCount(); index++)
    if (UO.GetScriptName(index) == "Worker")
    { UO.PauseResumeScript(index); break; }

1. Переключити паузу на ім'я - прямий скрипт

Параметри та порядок виконання:

  • 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;

2. Поставити працюючий запуск на паузу - функція сценарію

Параметри та порядок виконання:

  • Перевірка == 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;

3. Вибрати запуск по файлу - клас сценарію

Параметри та порядок виконання:

  • Замініть абсолютний шлях своїм. 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.

UO.PauseResumeScript(scriptIndex) — UO.PauseResumeScript(Any)

Параметри: scriptIndex (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "pauseresumescript": bridge.PauseResumeScript(Arg(0)); return InjectionValue.Unit;

UO.SetEvent

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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#-файли

Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

RegisterRoutine("HealthChanged", () => UO.Print("HP changed"));
UO.SetEvent("ChangeHitPoints", true, false, "HealthChanged");
await WaitAsync(5000);

1. Один раз скасувати незавершений target після смерті – прямий скрипт

Параметри та порядок виконання:

  • Спостереження триває вісім секунд. 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;

2. Попередження про витривалість: коротка форма — функція сценарію

Параметри та порядок виконання:

  • 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;

3. Переключити обробник мани без накопичення передплат — клас сценарію

Параметри та порядок виконання:

  • Перші дві секунди кожна виявлена ​​зміна викликає 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.

UO.SetEvent(name, stateValue) — UO.SetEvent(Any,Any)

Параметри: name (Any), stateValue (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "SetEvent": SetStateEvent(arguments); return true;

Внутрішній код реалізації, не самостійний скрипт.

public void SetEvent(InjectionValue name, InjectionValue stateValue)

            => SetEvent(name, stateValue, InjectionValue.True, new InjectionValue(string.Empty));

UO.SetEvent(name, stateValue, repeatOrHandler) — UO.SetEvent(Any,Any,Any)

Параметри: name (Any), stateValue (Any), repeatOrHandler (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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));

        }

UO.SetEvent(nameValue, stateValue, repeatValue, subNameValue) — UO.SetEvent(Any,Any,Any,Any)

Параметри: nameValue (Any), stateValue (Any), repeatValue (Any), subNameValue (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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;

        }

UO.SetEventProc

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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#-файли

Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

RegisterRoutine("HealthChanged", () => UO.Print("HP changed"));
UO.SetEventProc("ChangeHitPoints", "HealthChanged");
await WaitAsync(5000);

1. Слідкувати за змінами здоров'я протягом 10 секунд — прямий скрипт

Параметри та порядок виконання:

  • 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;

2. Стежити за маною та витривалістю під час підготовки – функція сценарію

Параметри та порядок виконання:

  • 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;

3. Помічати нові mobiles, потім відключити спостереження – клас сценарію

Параметри та порядок виконання:

  • 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.

UO.SetEventProc(eventname, procname) — UO.SetEventProc(Any,Any)

Параметри: eventname (Any), procname (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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;

                }

UO.SetPauseScriptOnDisconnectStatus

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

void UO.SetPauseScriptOnDisconnectStatus(object? value);

Змінює правило паузи скриптів у разі втрати з'єднання.

Параметри

  • value — 0 вимикає; будь-яке ненульове ціле включає.

Повернене значення

void - значення немає. Викликайте окремим рядком; завершення не підтверджує дію сервера.

Поведінка

  • SetPauseScriptOnDisconnectStatus задає _manager.PauseScriptsOnDisconnect = enabled != 0. Вже запущені скрипти не отримують команду PauseResumeScript.
  • Змінює налаштування клієнта. Значення не є результатом перевірки з'єднання та не підтверджує обробку сервером.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.

UO.Print("Calling UO.SetPauseScriptOnDisconnectStatus");
UO.SetPauseScriptOnDisconnectStatus(1);

1. Прямий виклик – прямий скрипт

Параметри та порядок виконання:

  • Змінює правило паузи скриптів у разі втрати з'єднання.
UO.SetPauseScriptOnDisconnectStatus(1);

2. Явний варіант – функція сценарію

Параметри та порядок виконання:

  • SetPauseScriptOnDisconnectStatus задає _manager.PauseScriptsOnDisconnect = enabled != 0. Вже запущені скрипти не отримують команду PauseResumeScript.
return  RunScenario();
 object? RunScenario()
{
    UO.SetPauseScriptOnDisconnectStatus(0);
    return null;
}

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Змінює налаштування клієнта. Значення не є результатом перевірки з'єднання та не підтверджує обробку сервером.
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.

UO.SetPauseScriptOnDisconnectStatus(value) — UO.SetPauseScriptOnDisconnectStatus(Any)

Параметри: value (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "setpausescriptondisconnectstatus": bridge.SetPauseScriptOnDisconnectStatus(Arg(0)); return InjectionValue.Unit;

UO.SetScriptName

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .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; }

1. Дати задачі зрозуміле ім'я - прямий скрипт

Параметри та порядок виконання:

  • 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;

2. Розрізнити завдання з різних файлів – функція сценарію

Параметри та порядок виконання:

  • Замініть 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) ?? "");

3. Додати стан у підпис - клас сценарію

Параметри та порядок виконання:

  • 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.

UO.SetScriptName(scriptIndex, value) — UO.SetScriptName(Any,Any)

Параметри: scriptIndex (Any), value (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "setscriptname": bridge.SetScriptName(Arg(0), Text(1)); return InjectionValue.Unit;

UO.StartScript

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

int UO.StartScript(object? scriptPath);

Параметри

Повернене значення

int: кількість активних запусків після прийнятого запуску; 65535 (0xFFFF) = помилка запуску. Це не індекс нового скрипта, не bool і не результат завершення.

Поведінка

  • Враховуються виконувані та призупинені запуски; завершені та отримані запит скасування виключаються. Скрипт, що працює, зазвичай враховує і себе. Просто завантажена вкладка IDE запуск не вважається.
  • Індекси – поточні позиції у порядку запуску. Запуск/зупинка скриптів може зрушити позиції. Різні дзвінки не утворюють загальний атомарний знімок; перед наступною командою керування перечитайте список.
  • "GetScriptsList" дає індекси, "GetScriptsCount" - кількість, "GetScriptState" - код з трьох станів. Не підміняйте одне одним і не вважайте будь-який ненульовий результат true.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.StartScript("Scripts/Worker.csx");
UO.Print("StartScript: " + Convert.ToString(result));

1. Перший виклик і результат – прямий скрипт

Параметри та порядок виконання:

  • Запускайте наведений 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;

2. Використання в циклі чи умові – функція сценарію

Параметри та порядок виконання:

  • Це окремий приклад спільного використання команд. Індексація масиву починається з нуля; перед зверненням перевіряйте довжину. 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;

3. Повна допоміжна функція – клас сценарію

Параметри та порядок виконання:

  • Під 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.

UO.StartScript(scriptPath) — UO.StartScript(Any)

Параметри: scriptPath (Any)

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "startscript": return new InjectionValue(bridge.StartScript(Text(0)));

UO.StopAllScripts

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

void UO.StopAllScripts();

Параметри

Параметрів немає.

Повернене значення

void — значення, що повертається, немає. Не порівнюйте дзвінок з true/1. Стан перевіряйте окремим читанням GetScriptState; результат такого читання - "0" (немає запуску), "1" (працює), "2" (пауза).

Поведінка

  • Працює лише із запусками поточного сеансу. Відкрита вкладка без виконання не є активним запуском. Зупинка не видаляє вихідний файл і не вимикає з'єднання з сервером.
  • Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
  • Аргументів немає. Скасуються виконувані та призупинені процедури, що очікують запуску запити та чергу повторних запусків. Скрипт, що викликає, теж отримує скасування: не поміщайте обов'язкове збереження/звіт після цієї команди. Інші профілі та процеси не торкаються.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.

UO.Print("Calling UO.StopAllScripts");
UO.StopAllScripts();

1. Безумовна загальна зупинка – прямий скрипт

Параметри та порядок виконання:

  • У команди порожні дужки. Здійсніть потрібне збереження до дзвінка. Сам контролер теж буде зупинено.
  • Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
UO.StopAllScripts();

2. Зупинитись при смерті персонажа - функція сценарію

Параметри та порядок виконання:

  • 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;

3. Загальна зупинка за п'ять секунд – клас сценарію.

Параметри та порядок виконання:

  • 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.

UO.StopAllScripts() — UO.StopAllScripts()

Параметри: Немає параметрів.

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "stopallscripts": bridge.StopAllScripts(); return InjectionValue.Unit;

UO.StopScript

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

void UO.StopScript(object? scriptIndex);

Запитує скасування одного активного запуску, у тому числі на паузі. Використовуйте, коли роботу цього запуску потрібно закінчити, а не продовжити пізніше.

Параметри

  • scriptIndex — Обов'язковий ScriptIndex — поточний індекс запуску: 0 позначає перший, далі 1, 2… Отримуйте його через GetScriptsList; це не serial, ім'я файлу і не результат StartScript. Негативний/відсутній індекс нічого не змінює.

Повернене значення

void — значення, що повертається, немає. Не порівнюйте дзвінок з true/1. Стан перевіряйте окремим читанням GetScriptState; результат такого читання - "0" (немає запуску), "1" (працює), "2" (пауза).

Поведінка

  • Працює лише із запусками поточного сеансу. Відкрита вкладка без виконання не є активним запуском. Зупинка не видаляє вихідний файл і не вимикає з'єднання з сервером.
  • Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька API-дзвінків не є атомарною операцією. Приклади розраховані відсутність паралельного зміни списку; шукайте потрібний запуск заново перед дією та не зберігайте індекс через UO.Wait.
  • Скасування кооперативне: будить очікування паузи і перевіряється двигуном; вже надіслані дії серверу не скасовуються. Скасований запуск відразу виключається з активного списку, хоча звільнення ресурсів може тривати. Не перевіряйте завершення за попереднім індексом: під ним може бути інший запуск.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

for (int index = 0; index < UO.GetScriptsCount(); index++)
    if (UO.GetScriptName(index) == "Worker")
    { UO.StopScript(index); break; }

1. Зупинити одну процедуру – прямий скрипт

Параметри та порядок виконання:

  • 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. Зупинити призупинений запуск - функція сценарію

Параметри та порядок виконання:

  • Код 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;

3. Зупинити запуск із певного файлу – клас сценарію

Параметри та порядок виконання:

  • Абсолютний шлях вибирає перший активний запуск файлу. Це не видалення файлу і не зупиняє всі процедури з цього файлу.
  • Індекси динамічні: після завершення іншого запуску позиції можуть зрушити. Декілька 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.

UO.StopScript(scriptIndex) — UO.StopScript(Any)

Параметри: scriptIndex (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

case "stopscript": bridge.StopScript(Arg(0)); return InjectionValue.Unit;

UO.SubExists

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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#-файли

Крім локальних делегатів, поточний менеджер підтримує явно завантажені C#-входи з ключем на кшталт Child.csx::Main. SubExists та FunRunning приймають такий ключ; CallSub запускає файл без Args, а Exec("exec Child.csx::Main 'north gate' 42") передає Args. Ключ із пробілами полягає в лапки всередині Exec. Унікальне коротке ім'я припустимо, неоднозначне ім'я не вибирає випадкового файлу. Локальна реєстрація має пріоритет. Файловий запуск отримує власний контекст та час життя у поточному світі/менеджері; локальні делегати належать до виконання, яке їх зареєструвало.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

RegisterRoutine("Hello", () => UO.Print("Hello"));
UO.Print("Registered flag: " + UO.SubExists("Hello"));

1. Запустити доступну необов'язкову процедуру – прямий скрипт

Параметри та порядок виконання:

  • Команда повертає 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;

2. Вибрати запасний обробник - функція сценарію

Параметри та порядок виконання:

  • 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;

3. Перевірити обидва визначення перед запуском – клас сценарію

Параметри та порядок виконання:

  • 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.

UO.SubExists(subrutineName) — UO.SubExists(String)

Параметри: subrutineName (String)

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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;

UO.Terminate

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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() вибирає процедуру по порядку запуску, а не по імені, рядку редактора, часу останньої дії або порядку відображення. Поставлена ​​на паузу процедура також вважається запущеною.
  • Очищається локальний приціл, що належить цьому запуску, і скасовується автоматичний маршрут, що залишився. Скасування руху виконується на ігровому потоці; якщо маршрут вже замінено іншим запуском або користувачем, колишній власник його не зупиняє. Надіслані серверу кроки не відгукуються.
  • Команда залишається доступною при увімкненому налаштуванні одного одночасного запуску. Скасована процедура звільняє місце лише після очищення свого робочого потоку; раніше новий запуск пропускається.
  • При зупинці на ім'я також скасовуються відповідні відкладені запуски. Завершені процедури не змінюються. Про відсутність відповідного запуску клієнт повідомляє статус. Виклик стороннього нативного плагіна, який не підтримує скасування, не можна безпечно перервати примусовим знищенням потоку.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .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");

1. Зупинити харвест на ім'я, залишивши решту процедур — прямий скрипт

Приклад запитує скасування вже запущеного harvest.csx::Main. Повідомлення не підтверджує завершення його finally або відкат ігрових дій.

var procedureName = "harvest.csx::Main";
UO.Terminate(procedureName);
UO.Print("Cancellation requested for harvest.csx::Main");

2. Вибрати 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;
}

3. Сумісна консольна форма через Exec – клас сценарію

Рядок 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;
    }
}

4. Зупинити останній запуск за низького здоров'я — прямий скрипт

Параметри та порядок виконання:

  • Форма без аргументів вибирає останній запущений скрипт, включаючи поставлений паузу. Це політика прикладу, а чи не обов'язкова реакція низьке здоров'я; повідомлення виводиться до запиту скасування.
if (UO.GetHP() <= 30)
{
    UO.Print("Low health: requesting cancellation of the most recent run");
    UO.Terminate();
}

Реалізація команди

C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.

UO.Terminate() — UO.Terminate()

Параметри: Немає параметрів.

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

public void Terminate() => bridge.Terminate(string.Empty);

UO.Terminate(subrutineName) — UO.Terminate(String)

Параметри: subrutineName (String)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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);

UO.TerminateAll

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

void UO.TerminateAll();

Параметри

Параметрів немає.

Повернене значення

void: немає результату. Команда запитує скасування всіх поточних запусків і повертає управління коду, що викликає, якщо він сам не був скасований. Очищення робочих потоків здійснюється після спрацювання їх перевірок скасування.

Поведінка

  • Точний синтаксис - UO.TerminateAll(), без пробілу всередині імені та без аргументів. UO.Terminate("all") підтримується як сумісний альтернативний запис.
  • Зупиняються працюючі процедури, процедури на ручній паузі та на точці зупинки, вбудовані очікування та зареєстровані відкладені запуски. Повторний дзвінок за відсутності роботи безпечний.
  • Зняття локальних прицілів та автоматичних маршрутів враховує їх власників. маршрут зупиненого скрипта, що залишився, скасовується на ігровому потоці; новий маршрут користувача, який його замінив, зберігається. Вже надіслані пакети руху не скасовуються.
  • Скасування не відкочує вже надіслані серверу дії. Код сторонніх нативних плагінів без підтримки скасування не можна безпечно знищити разом із потоком. Нові явні запуски після виконання команди дозволені; при включеній галочці вони чекають на звільнення місця в тому сенсі, що спроба до завершення очищення пропускається, а не ставиться в чергу.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.

UO.Print("Calling UO.TerminateAll");
UO.TerminateAll();

1. Зупинити всі скрипти з перевірки всередині робочого скрипта – прямий скрипт

Параметри та порядок виконання:

  • 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;

2. Сумісна форма з all - функція сценарію

Параметри та порядок виконання:

  • У цьому альтернативному записі використовується UO.Terminate з одним параметром subrutineName="all". Це еквівалент UO.TerminateAll().
  • Рядок all – спеціальне значення, а не ім'я процедури, яке потрібно оголосити. Скасується і EmergencyStop.
  • Для аварійної ігрової клавіші використовуйте однорядкову команду з першого прикладу: окрема процедура EmergencyStop сама підпорядковується забороні паралельних запусків.
return  RunScenario();
 object? RunScenario()
{
    UO.Print("Stopping all C# scripts");
    UO.Terminate("all");
    return null;
}

3. Зупинити спільну роботу, якщо обов'язковий об'єкт став недоступним — клас сценарію

Параметри та порядок виконання:

  • 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;
}

4. Зупинити всю роботу після втрати з'єднання.

Параметри та порядок виконання:

  • За відсутності з'єднання вибирається зупинка всіх запусків. Команда не повертає кількість скасованих скриптів і скасовує поточний запуск.
if (UO.Connected() == 0)
{
    UO.Print("Disconnected: requesting cancellation of every active script");
    UO.TerminateAll();
}

Реалізація команди

C# враховує регістр. Використовуйте точне ім’я UO. Числові прапорці порівнюйте з 0; bool використовуйте лише там, де сигнатура повертає bool.

UO.TerminateAll() — UO.TerminateAll()

Параметри: Немає параметрів.

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

public void TerminateAll() => bridge.Terminate("all");

UO.Time

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

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() та дві позначки одного запуску. Календарний годинник може перевестися назад.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.Time();
UO.Print("Time: " + Convert.ToString(result));

1. Показати окремі поля часу – прямий скрипт

Параметри та порядок виконання:

  • 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));

2. Дозволити серію лише у вечірньому інтервалі – функція сценарію

Параметри та порядок виконання:

  • 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;

3. Врахувати інтервал через північ — клас сценарію

Параметри та порядок виконання:

  • 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.

UO.Time() — UO.Time()

Параметри: Немає параметрів.

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

public int Time()

        {

            var now = timeSource.Now;

            return now.Hour * 10000 + now.Minute * 100 + now.Second;

        }

UO.Timer

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

int UO.Timer();

Читає час роботи поточного runtime в десятих частках секунди. Підходить для власних затримок та позначок дій.

Параметри

Параметрів немає.

Повернене значення

int 0..2147483647; одиниця - 100 мс. При 399 мс повернеться 3. Це показує годинник, а не true/false і не залишок перезаряджання.

Поведінка

  • Параметрів немає, форм із аргументами немає. Порожні дужки лише читають час: виклик не чекає, не запускає таймер та не відправляє пакети у гру.
  • Початок відліку належить цьому екземпляру runtime. Нова запущена процедура може отримати новий годинник; не можна порівнювати значення різних запусків або зберігати їх як абсолютну дату. Під час UO.Wait та паузи скрипту реальний час продовжує йти.
  • Дробна частина десятих відкидається. Приблизно через 2485.5 діб число досягає 2147483647 і залишається таким, не переповнюючись.
  • Це ваша затримка, а не серверна перезарядка навички/заклинання та не підтвердження успіху. Команда не дозволяє обходити обмеження сервера на рух, заклинання чи скрипти.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.Timer();
UO.Print("Timer: " + Convert.ToString(result));

1. Виміряти тривалість операції - прямий скрипт

Параметри та порядок виконання:

  • 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)));

2. Обмежити очікування вже запрошеного прицілу трьома секундами – функція сценарію

Параметри та порядок виконання:

  • Межа 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;

3. Власна функція інтервалу між спробами – клас сценарію.

Параметри та порядок виконання:

  • 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.

UO.Timer() — UO.Timer()

Параметри: Немає параметрів.

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

public int Timer() => (int)Math.Max(0d, Math.Min(int.MaxValue, timeSource.SinceStart.TotalMilliseconds / 100d));

UO.Wait

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

void UO.Wait(object? waitTimeMS);

Зупиняє поточний скрипт на задану кількість мілісекунд. Корисно між повторними перевірками стану, щоб скрипт не крутив безперервний цикл.

Параметри

  • waitTimeMS — Цілі години в мілісекундах: 1000 = одна секунда. Використовуйте 0..2147483647. Це не кількість кроків, не секунди і не тримають підтвердження сервера.

Повернене значення

void - результату немає. Викликайте окремим рядком. Закінчення затримки не означає, що предмет перемістився, завершення заклинання або з'єднання встановлено: потрібний стан перевіряйте окремо.

Поведінка

  • Нуль не створює реальної затримки та не підходить як пауза у швидкому циклі. Негативний час не означає нескінченність: UO.Wait зводить його до 0; UO.Wait/sleep можуть відхилити його при активному callback, а в клієнтському мосту без них воно не чекає. Для скрипта, що переноситься, використовуйте тільки невід'ємний час.

Приклад .csx

UO.Wait(100);
// For an asynchronous script, use the host helper:
await WaitAsync(100);

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.

UO.Print("Calling UO.Wait");
UO.Wait(250);

1. UO.Wait - 1 - прямий скрипт

Параметри та порядок виконання:

  • 250 - чверть секунди. Наступний рядок виконується після очікування; повідомлення Delay complete — текст прикладу, а чи не повернутий результат.
UO.Wait(250);
UO.Print("Delay complete");

2. UO.Wait — 2 — функція сценарію

Параметри та порядок виконання:

  • 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;

3. UO.Wait - 3 - клас сценарію

Параметри та порядок виконання:

  • Цикл робить рівно три читання ваги. Між читаннями є дві паузи по 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.

UO.Wait(waitTimeMS) — UO.Wait(Any)

Параметри: waitTimeMS (Any)

Результат: void / Unit.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

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;

UO.Waiting

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

int UO.Waiting();

Перевіряє, чи залишилися підготовлені відповіді у черзі target.

Параметри

Параметрів немає.

Повернене значення

int 1 — є невідмінна відкладена мета об'єкта, тайла або скасування наступного прицілу; 0 - черга порожня. Не наявність відкритого курсора; для курсору використовуйте TargetPresent/Targeting.

Результат команди — числовий прапор: 1 означає виконану умову, 0 — невиконану. Після var result = команда (...) перевіряйте if (result != 0) або if (result == 0). Збережіть результат одного виклику: повторний виклик може виконати дію знову або прочитати стан, що вже змінився.

Поведінка

  • Читається черга всього клієнта. Якщо одночасно працюють кілька процедур, враховуються відповіді кожної з них.
  • Нуль означає лише відсутність очікуваної відповіді. Він не підтверджує успішне застосування навички або заклинання на сервері.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

var result = UO.Waiting();
UO.Print("Waiting: " + Convert.ToString(result));

1. Перевірити підготовку – прямий скрипт

Параметри та порядок виконання:

  • Після WaitTargetSelf і до серверного target очікується 1.
  • CancelWaitTarget прибирає чергу; наступна перевірка дасть 0.
UO.WaitTargetSelf();
UO.Print(Convert.ToString(UO.Waiting()));
UO.CancelWaitTarget();

2. Обмежено дочекатися витрачання відповіді – функція сценарію

Параметри та порядок виконання:

  • Параметрів перевірки немає. 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;

3. Показати різницю між чергою та прицілом – клас сценарію

Параметри та порядок виконання:

  • Перший рядок показує відкладені відповіді, другий стан прицілу.
  • Можлива черга без курсору та курсор без черги; ці значення не взаємозамінні.
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.

UO.Waiting() — UO.Waiting()

Параметри: Немає параметрів.

Результат: int / Integer.

Під час виклику:

Внутрішній код реалізації, не самостійний скрипт.

public int Waiting() => bridge.GetWaitTargetQueue().Length > 0 ? 1 : 0;

Clone this wiki locally