Skip to content

RU UO Topic files json data

Codex edited this page Oct 12, 2026 · 4 revisions

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

Файлы / JSON / Данные

Главная · C# · IDE · UO API · A–Z · Примеры · Языки

Файлы, JSON, массивы и коллекции C#, а также совместимые помощники UO. Встроенные функции C# записываются без UO.

Разделы

Тема Команды и пояснения
File C# и стандартная библиотека
JSON Parse C# и стандартная библиотека
JSON Load C# и стандартная библиотека))
JSON Save C# и стандартная библиотека
JSON Stringify C# и стандартная библиотека
List C# и стандартная библиотека
Dictionary C# и стандартная библиотека
Arrays C# и стандартная библиотека · C# и стандартная библиотека
MemoryStream C# и стандартная библиотека

Все команды темы

Коллекции совместимости

UO.GetArrayLength · UO.GetWord · UO.GetWordCount

Random Значения

UO.Random

C# и стандартная библиотека · C# и стандартная библиотека · C# и стандартная библиотека

Примеры по теме

В каждой карточке команды есть несколько самостоятельных сценариев: прямой код, функции и классы. Ниже приведены отдельные короткие сценарии; ограничения и полный разбор находятся в карточках.

UO.GetArrayLength

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

dynamic[] amounts = new dynamic[checked((int)(2) + 1)];
amounts[0] = 50;
amounts[1] = 75;
amounts[2] = 25;
var total = 0;
for (int index = (int)(0); index <= UO.GetArrayLength(amounts) - 1; index += (int)(1))
{
    total += amounts[index];
}
return total;

UO.GetWord

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

return ReadX("move   1445 1690");

dynamic ReadX(dynamic text)
{
    if (Truth(UO.GetWordCount(text) != 3))
    {
        return -1;
    }
    if (Truth(UO.GetWord(text, 0) != "move"))
    {
        return -1;
    }
    var xText = UO.GetWord(text, 1);
    if (!(Truth(IsNumeric(xText))))
    {
        return -1;
    }
    var x = Convert.ToDouble(xText);
    if (Truth(Convert.ToString(x) == "NaN") || Truth(x < 0) || Truth(x > 65535))
    {
        return -1;
    }
    if (Truth(x != Math.Truncate(x)))
    {
        return -1;
    }
    return Convert.ToInt32(x);
}

bool IsNumeric(object? value) => double.TryParse(Convert.ToString(value), System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out _);
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

Полное описание команд


UO.GetArrayLength

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

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

dynamic UO.GetArrayLength(object? arg);

Считает непосредственные ячейки массива для ограниченного перебора и безопасного чтения индекса.

Параметры

Возвращает

int >= 0. Пустой Array и значение другого вида дают 0: только по результату нельзя проверить тип. Это количество, а не bool и не последний индекс.

Поведение

  • Локальная проверка: не отправляет запрос серверу, не перемещает предметы и не изменяет массив. В примерах заданы учебные данные, а не живой инвентарь.
  • Проверяет вид значения и читает Array.Length без обхода и суммирования. объявление переменной values(2) создаёт три ячейки, индексы 0..2, включая незаполненные.
  • Вложенные элементы рекурсивно не считаются. Для строки есть Len, для List/Dictionary — их Count. UO.GetArrayLength — совместимое имя той же локальной проверки.

Самостоятельные C#-скрипты

Каждый пример можно сохранить отдельным файлом .csx и запускать в IDE. Объект UO и функции ожидания предоставляет host текущей игровой сессии. Демонстрационные serial, имена, координаты и адреса замените своими.

Простой пример

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

Результат одного вызова выводится в журнал. Число не преобразуется в bool; для массива показано количество элементов.

object? result = UO.GetArrayLength(new[] { 10, 20, 30 });
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));

1. Сложить количества из ограниченного списка — прямой скрипт

Параметры и ход выполнения:

  • объявление переменной amounts(2) создаёт три записи. Цикл обходит индексы 0..2 и возвращает 150. Количества складывает цикл, а не ArrayLength.
  • Локальная проверка: не отправляет запрос серверу, не перемещает предметы и не изменяет массив. В примерах заданы учебные данные, а не живой инвентарь.
dynamic[] amounts = new dynamic[checked((int)(2) + 1)];
amounts[0] = 50;
amounts[1] = 75;
amounts[2] = 25;
var total = 0;
for (int index = (int)(0); index <= UO.GetArrayLength(amounts) - 1; index += (int)(1))
{
    total += amounts[index];
}
return total;

2. Отдельно посчитать точки и поля координат — функция сценария

Параметры и ход выполнения:

  • В route две точки Array, в каждой по три ячейки координат. Результат 2|3, а не шесть. Персонаж не движется.
  • Локальная проверка: не отправляет запрос серверу, не перемещает предметы и не изменяет массив. В примерах заданы учебные данные, а не живой инвентарь.
return  RunScenario();
 object? RunScenario()
{
    dynamic[] first = new dynamic[checked((int)(2) + 1)];
    first[0] = 100;
    first[1] = 200;
    first[2] = 0;
    dynamic[] second = new dynamic[checked((int)(2) + 1)];
    second[0] = 101;
    second[1] = 200;
    second[2] = 0;
    dynamic[] route = new dynamic[checked((int)(1) + 1)];
    route[0] = first;
    route[1] = second;
    return Convert.ToString(UO.GetArrayLength(route)) + "|" + Convert.ToString(UO.GetArrayLength(route[0]));
    return null;
}

3. Проверить первый индекс — класс сценария

Параметры и ход выполнения:

  • Строка даёт 0; Main возвращает no route до обращения к индексу. Проверка подходит и для пустого Array, но не различает эти случаи.
  • Локальная проверка: не отправляет запрос серверу, не перемещает предметы и не изменяет массив. В примерах заданы учебные данные, а не живой инвентарь.
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 route = "not an array";
        if (Truth(UO.GetArrayLength(route) == 0))
        {
            return "no route";
        }

        return route[0];
        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.GetArrayLength(arg) — UO.GetArrayLength(Any)

Параметры: arg (Any)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

public static InjectionValue GetArrayLength(InjectionValue arg) => arg.Kind==InjectionValueKind.Array?new InjectionValue(arg.Array.Length):InjectionValue.Zero;

UO.GetWord

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

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

string UO.GetWord(object? value, object? wordIndex);
string UO.GetWord(object? value, object? wordIndex, object? delimiter);

Получает отдельное слово или поле из текста. Пригодится для разбора координат, списка приоритетов или сохранённой настройки скрипта.

Параметры

  • value — Исходная строка. Функция разбирает именно переданный текст: не читает журнал, файл, экипировку или мир самостоятельно.
  • wordIndex — Целый индекс слова от 0: 0 — первое, 1 — второе. Отрицательный индекс и индекс не меньше количества слов возвращают пустую строку.
  • delimiter — Необязательный разделитель. Без него, с "" или с одним пробелом " " текст делится по любым пробельным символам Unicode, включая табуляцию и перевод строки. Иной разделитель — точная последовательность целиком: "::" означает два двоеточия подряд, а не каждое двоеточие. Пустые части отбрасываются; непустые части не обрезаются.

Возвращает

string — выбранная непустая часть, либо "", если индекс отсутствует. Это текст, а не ID, type или число: для числа отдельно проверьте IsNumeric и преобразуйте значение.

Поведение

  • Работает локально, без пакетов и игровых действий. GetWord и UO.GetWord вызывают один обработчик; GetWordCount и UO.GetWordCount также совпадают. Каждый вызов заново разделяет весь текст. В цикле сохраните количество заранее; для большого многократного разбора лучше хранить уже разобранные поля в массиве. Это не CSV-парсер: кавычки не защищают разделители, пустые столбцы теряются.
  • GetWord · GetWordCount · IsNumeric

Самостоятельные C#-скрипты

Каждый пример можно сохранить отдельным файлом .csx и запускать в IDE. Объект UO и функции ожидания предоставляет host текущей игровой сессии. Демонстрационные serial, имена, координаты и адреса замените своими.

Простой пример

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

Результат одного вызова выводится в журнал. Число не преобразуется в bool; для массива показано количество элементов.

var result = UO.GetWord("red green blue", 1);
UO.Print("GetWord: " + Convert.ToString(result));

1. UO.GetWord — 1 — прямой скрипт

Параметры и ход выполнения:

  • ReadX получает строку "move 1445 1690". Проверяет три слова и имя move; индекс 1 выбирает X. IsNumeric проверяет текст, Convert.ToInt32 возвращает 1445. Это только разбор настройки; персонаж не двигается. При неверной форме возвращается -1.
  • ReadX также требует целый X в диапазоне 0..65535 перед Convert.ToInt32; NaN, бесконечность и дробное X отклоняются. Y здесь не проверяется.
return ReadX("move   1445 1690");

dynamic ReadX(dynamic text)
{
    if (Truth(UO.GetWordCount(text) != 3))
    {
        return -1;
    }
    if (Truth(UO.GetWord(text, 0) != "move"))
    {
        return -1;
    }
    var xText = UO.GetWord(text, 1);
    if (!(Truth(IsNumeric(xText))))
    {
        return -1;
    }
    var x = Convert.ToDouble(xText);
    if (Truth(Convert.ToString(x) == "NaN") || Truth(x < 0) || Truth(x > 65535))
    {
        return -1;
    }
    if (Truth(x != Math.Truncate(x)))
    {
        return -1;
    }
    return Convert.ToInt32(x);
}

bool IsNumeric(object? value) => double.TryParse(Convert.ToString(value), System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out _);
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

2. UO.GetWord — 2 — функция сценария

Параметры и ход выполнения:

  • PriorityAt получает список "mage||tank|archer|" и index=1. Разделитель | отбрасывает пустые элементы, поэтому результат tank. Имена произвольные; здесь они не регистрируют ClassMask и не проверяют одежду. Используйте те же правила разделения при подсчёте и выборе.
return  RunScenario();
 object? RunScenario()
{
    return PriorityAt("mage||tank|archer|", 1);
    return null;
}

dynamic PriorityAt(dynamic names, dynamic index)
{
    return UO.GetWord(names, index, "|");
}

3. UO.GetWord — 3 — класс сценария

Параметры и ход выполнения:

  • ReadPlace делит "Britain::Bank:west" точным разделителем ::. Индекс 1 возвращает Bank:west, внутреннее одиночное двоеточие остаётся. Если нет ровно двух непустых частей, помощник возвращает "". Пробелы вокруг частей сохраняются.
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()
    {
        return ReadPlace("Britain::Bank:west");
        return null;
    }

    dynamic ReadPlace(dynamic text)
    {
        if (Truth(UO.GetWordCount(text, "::") != 2))
        {
            return "";
        }

        return UO.GetWord(text, 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.GetWord(value, wordIndex) — UO.GetWord(String,Integer)

Параметры: value (String), wordIndex (Integer)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

private static string GetWord(string value,int wordIndex) => GetWord(value,wordIndex," ");

UO.GetWord(value, wordIndex, delimiter) — UO.GetWord(String,Integer,String)

Параметры: value (String), wordIndex (Integer), delimiter (String)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

private static string GetWord(string value,int wordIndex,string delimiter)
        {
            var words=SplitWords(value,delimiter);return wordIndex>=0&&wordIndex<words.Length?words[wordIndex]:string.Empty;
        }

UO.GetWordCount

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

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

int UO.GetWordCount(object? value);
int UO.GetWordCount(object? value, object? delimiter);

Считает непустые поля текста. Позволяет проверить число координат перед разбором и определить границы перебора списка.

Параметры

  • value — Исходная строка. Функция разбирает именно переданный текст: не читает журнал, файл, экипировку или мир самостоятельно.
  • delimiter — Необязательный разделитель. Без него, с "" или с одним пробелом " " текст делится по любым пробельным символам Unicode, включая табуляцию и перевод строки. Иной разделитель — точная последовательность целиком: "::" означает два двоеточия подряд, а не каждое двоеточие. Пустые части отбрасываются; непустые части не обрезаются.

Возвращает

int — количество непустых частей. Пустая строка и строка только из разделителей дают 0. Это счётчик, а не bool: 2 тоже допустимый результат; проверяйте count > 0 или нужное точное количество.

Поведение

  • Работает локально, без пакетов и игровых действий. GetWord и UO.GetWord вызывают один обработчик; GetWordCount и UO.GetWordCount также совпадают. Каждый вызов заново разделяет весь текст. В цикле сохраните количество заранее; для большого многократного разбора лучше хранить уже разобранные поля в массиве. Это не CSV-парсер: кавычки не защищают разделители, пустые столбцы теряются.
  • GetWord · GetWordCount · IsNumeric

Самостоятельные C#-скрипты

Каждый пример можно сохранить отдельным файлом .csx и запускать в IDE. Объект UO и функции ожидания предоставляет host текущей игровой сессии. Демонстрационные serial, имена, координаты и адреса замените своими.

Простой пример

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

Результат одного вызова выводится в журнал. Число не преобразуется в bool; для массива показано количество элементов.

var result = UO.GetWordCount("red green blue");
UO.Print("GetWordCount: " + Convert.ToString(result));

1. UO.GetWordCount — 1 — прямой скрипт

Параметры и ход выполнения:

  • HasPoint принимает "1445 1690 0". Требует ровно три слова и числовой текст в каждом, затем возвращает 1; иначе 0. Это только проверка формы, а не допустимости карты, границ координат или проходимости. GetWordCount здесь возвращает 3, а bool возвращает наш помощник.
  • HasPoint дополнительно отклоняет NaN и бесконечности, которые сам IsNumeric может принять. Дробные конечные числа допускаются; перед движением нужна отдельная проверка целых игровых координат.
return HasPoint("1445 1690 0");

dynamic HasPoint(dynamic text)
{
    if (Truth(UO.GetWordCount(text) != 3))
    {
        return 0;
    }
    var i = 0;
    while (Truth(i < 3))
    {
        if (!(Truth(IsNumeric(UO.GetWord(text, i)))))
        {
            return 0;
        }
        var value = Convert.ToString(Convert.ToDouble(UO.GetWord(text, i)));
        if (Truth(value == "NaN") || Truth(value == "Infinity") || Truth(value == "-Infinity"))
        {
            return 0;
        }
        i = i + 1;
    }
    return 1;
}

bool IsNumeric(object? value) => double.TryParse(Convert.ToString(value), System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out _);
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

2. UO.GetWordCount — 2 — функция сценария

Параметры и ход выполнения:

  • JoinPriorities получает "mage||tank|archer|". Один раз считает три непустых элемента, перебирает индексы 0..2 и возвращает "mage > tank > archer". Начальные, конечные и повторные | не создают отдельный приоритет.
return  RunScenario();
 object? RunScenario()
{
    return JoinPriorities("mage||tank|archer|");
    return null;
}

dynamic JoinPriorities(dynamic names)
{
    var count = UO.GetWordCount(names, "|");
    var i = 0;
    var result = "";
    while (Truth(i < count))
    {
        if (Truth(i > 0))
        {
            result = result + " > ";
        }

        result = result + UO.GetWord(names, i, "|");
        i = i + 1;
    }

    return result;
}

bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

3. UO.GetWordCount — 3 — класс сценария

Параметры и ход выполнения:

  • CountPlaces получает "Britain::Bank:west::". Разделитель :: даёт два поля, конечное пустое поле удаляется: результат 2. Одиночное : внутри Bank:west не разделяет текст. Это не перечень городов из клиента, а пример вашего формата настройки.
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()
    {
        return CountPlaces("Britain::Bank:west::");
        return null;
    }

    dynamic CountPlaces(dynamic text)
    {
        return UO.GetWordCount(text, "::");
    }
}

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

C# учитывает регистр. Используйте точное имя UO. Числовые флаги сравнивайте с 0; bool используйте только там, где сигнатура возвращает bool.

UO.GetWordCount(value) — UO.GetWordCount(String)

Параметры: value (String)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

private static int GetWordCount(string value) => GetWordCount(value," ");

UO.GetWordCount(value, delimiter) — UO.GetWordCount(String,String)

Параметры: value (String), delimiter (String)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

private static int GetWordCount(string value,string delimiter) => SplitWords(value,delimiter).Length;

UO.Random

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

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

int UO.Random(object? max);
int UO.Random(object? min, object? max);

Возвращает случайное целое число. Новая форма UO.Random(min, max) выбирает число ОТ min ДО max включительно. Прежняя форма UO.Random(max) сохранена: она выбирает от 0 до max−1. Результат можно сохранить в переменную и использовать как задержку, координату, индекс или условие.

Параметры

  • min — Первый аргумент ТОЛЬКО двухаргументной формы — включённая нижняя граница, целое от −2147483648 до 2147483647. Может быть отрицательной, нулём или положительной. Должна быть не больше max. В одноаргументной форме min отсутствует, а переданное число означает max.
  • max — В двухаргументной форме — второй аргумент, включённая верхняя граница int от −2147483648 до 2147483647. В прежней одноаргументной форме — единственный аргумент, ИСКЛЮЧЁННАЯ верхняя граница, целое от 0 до 2147483647; Random(0) возвращает 0. Отрицательное max в одноаргументной форме недопустимо.

Возвращает

int — одно псевдослучайное целое число. При двух аргументах min ≤ результат ≤ max; обе границы могут выпасть. При одном положительном аргументе 0 ≤ результат < max. Повторение ранее выпавшего числа допустимо: команда не выбирает числа без повторений.

Поведение

  • Поддерживаются ровно две формы: UO.Random(max) и UO.Random(min, max). Вызов без аргументов не зарегистрирован. Для диапазона «от и до» используйте два аргумента.
  • Random(5, 5) всегда возвращает 5. Random(10, 1) сообщает ошибку диапазона: границы не переставляются молча. Random(-10, -1) корректен, потому что −10 меньше −1.
  • Обе границы — целые int; для десятичных долей можно выбрать целые единицы нужного масштаба и затем разделить. Например, Random(0, 100) / 100.0 даёт дискретные значения от 0 до 1 с шагом 0,01.
  • Полный диапазон Random(-2147483648, 2147483647) допустим. Реализация не прибавляет 1 к max в int и поэтому не переполняется на верхней границе. Для широких диапазонов используется отбрасывание лишних значений, чтобы остаток от деления не смещал выбор.
  • Вызов вычисляет число локально, не отправляет пакеты и сам по себе не делает паузу. Для случайной паузы передайте результат в UO.Wait. Минимальную необходимую серверу задержку должен сохранять ваш скрипт.
  • Сохраните результат в var, если одно и то же число нужно несколько раз. Два отдельных вызова Random могут вернуть разные значения. Команда не проверяет, допустима ли выбранная клетка для движения или переноса: это проверяет соответствующая игровая команда.

Самостоятельные C#-скрипты

Каждый пример можно сохранить отдельным файлом .csx и запускать в IDE. Объект UO и функции ожидания предоставляет host текущей игровой сессии. Демонстрационные serial, имена, координаты и адреса замените своими.

Простой пример

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

Результат одного вызова выводится в журнал. Число не преобразуется в bool; для массива показано количество элементов.

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

1. Случайное число от 1 до 6 — прямой скрипт

Параметры и ход выполнения:

  • min получает lower=1, max получает upper=6. Возможны ровно шесть значений: 1, 2, 3, 4, 5 и 6.
  • roll хранит одно полученное число. Print выводит именно его; Convert.ToString преобразует int в строку. Повторный запуск может дать то же число.
var lower = 1;
var upper = 6;
var roll = UO.Random(lower, upper);
UO.Print("Roll: " + Convert.ToString(roll));

2. Случайная пауза между 350 и 700 миллисекундами — функция сценария

Параметры и ход выполнения:

  • min=350 и max=700 задают включённые границы задержки. Результат, например 350, 512 или 700, записывается в delay.
  • UO.Wait получает один аргумент delay в миллисекундах. Пауза происходит в UO.Wait; Random только вычисляет число.
  • Подберите нижнюю границу под действия и требования вашего сервера. Случайная задержка не заменяет ожидание ответа сервера, если следующему действию нужен этот ответ.
return  RunScenario();
 object? RunScenario()
{
    var delay = UO.Random(350, 700);
    UO.Print("Waiting " + Convert.ToString(delay) + " ms");
    UO.Wait(delay);
    UO.Print("Wait finished");
    return null;
}

3. Выбрать одно из трёх действий условием — класс сценария

Параметры и ход выполнения:

  • min=1, max=3: choice равен 1, 2 или 3. Каждой ветке соответствует одно из допустимых чисел.
  • Вызов Random выполняется один раз до if. Если вызывать его заново в каждом условии, это будут разные выборы.
  • Замените Print нужными действиями вашего скрипта, сохранив проверки условий, дальности и ответа сервера для этих действий.
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 choice = UO.Random(1, 3);
        if (Truth(choice == 1))
        {
            UO.Print("First action");
        }
        else
        {
            if (Truth(choice == 2))
            {
                UO.Print("Second action");
            }
            else
            {
                UO.Print("Third action");
            }
        }

        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. Выбрать место для MassMove внутри рюкзака — прямой скрипт

Параметры и ход выполнения:

  • Первый Random: min=50, max=90, результат x. Второй: min=60, max=100, результат y. Это две независимые координаты внутри контейнера, не экранные координаты и не координаты карты.
  • В MassMove delay=350 мс, quantity=10 целых items, type=0 определяется первым ручным переносом, destination=backpack, x/y берутся из переменных, z=0.
  • После команды перетащите образец мышью из исходного контейнера. Всё это включение MassMove использует одну выбранную позицию. Для случайной позиции каждого отдельного предмета нужен цикл с отдельными MoveItem, а не один вызов MassMove.
  • Выберите диапазон X/Y внутри доступной области вашего рюкзака. Сервер может изменить размещение предметов.
var x = UO.Random(50, 90);
var y = UO.Random(60, 100);
UO.MassMove(350, 10, 0, "backpack", x, y, 0);
UO.Print("Drag a source item; position: " + Convert.ToString(x) + ", " + Convert.ToString(y));

5. Отрицательное смещение относительно исходной координаты — функция сценария

Параметры и ход выполнения:

  • В обоих вызовах min=−2 и max=2: возможны −2, −1, 0, 1, 2. GetX/GetY без аргументов читают координаты персонажа.
  • x/y — лишь рассчитанная клетка в квадрате вокруг персонажа. Этот пример не начинает движение и не бросает предметы.
  • Случайная клетка может оказаться непроходимой или за границей карты. Перед игровым действием используйте подходящие проверки координат и маршрута.
return  RunScenario();
 object? RunScenario()
{
    var offsetX = UO.Random(-2, 2);
    var offsetY = UO.Random(-2, 2);
    var x = UO.GetX() + offsetX;
    var y = UO.GetY() + offsetY;
    UO.Print("Candidate tile: " + Convert.ToString(x) + ", " + Convert.ToString(y));
    return null;
}

6. Сохранённая совместимость с Random(max) — класс сценария

Параметры и ход выполнения:

  • В Random(count) есть только max=10: верхняя граница исключена, возможны 0..9. Число 10 не выпадает.
  • В Random(0, count−1) min=0 и max=9 включительно: допустимый диапазон тот же, но вызов делает новый независимый выбор.
  • count должен быть положительным для выбора индекса. Особый совместимый случай Random(0)=0 не означает, что у пустой коллекции существует элемент с индексом 0.
return  new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
    private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
    private readonly Func<int, Task> WaitAsync;
    private readonly string[] Args;
    private readonly CancellationToken Cancellation;
    private readonly Action Checkpoint;
    public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
    {
        UO = api;
        WaitAsync = wait;
        Args = args;
        Cancellation = cancellation;
        Checkpoint = checkpoint;
    }

     public object? RunScenario()
    {
        var count = 10;
        var index = UO.Random(count);
        var equivalent = UO.Random(0, count - 1);
        UO.Print("Index 0..9: " + Convert.ToString(index));
        UO.Print("Another independent index: " + Convert.ToString(equivalent));
        return null;
    }
}

7. Равные границы и полный диапазон int — прямой скрипт

Параметры и ход выполнения:

  • min=7 и max=7 дают единственный результат 7.
  • min=−100 и max=−50 дают только отрицательные числа, включая обе границы.
  • Последний вызов охватывает весь знаковый 32-битный int. Его результат может быть положительным, отрицательным или нулём.
  • Границы передаются от меньшей к большей. Ошибочный вызов Random(10, 1) останавливается с сообщением min must not exceed max; его не нужно использовать для перевёрнутого диапазона.
var fixedValue = UO.Random(7, 7);
var negative = UO.Random(-100, -50);
var signedValue = UO.Random(-2147483648, 2147483647);
UO.Print("Fixed: " + Convert.ToString(fixedValue));
UO.Print("Negative: " + Convert.ToString(negative));
UO.Print("Signed Integer: " + Convert.ToString(signedValue));

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

C# учитывает регистр. Используйте точное имя UO. Числовые флаги сравнивайте с 0; bool используйте только там, где сигнатура возвращает bool.

UO.Random(max) — UO.Random(Integer)

Параметры: max (Integer)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

public int Random(int max)

        {

            lock (randomSync) return random.Next(max);

        }

UO.Random(min, max) — UO.Random(Integer,Integer)

Параметры: min (Integer), max (Integer)

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

При вызове:

Внутренний код реализации, не самостоятельный скрипт.

public int Random(int min, int max)

        {

            if (min > max)

                throw new NativeSubrutineException("UO.Random(min, max): min must not exceed max.");

            if (min == max) return min;

            long count = (long)max - min + 1;

            lock (randomSync)

            {

                if (count <= int.MaxValue)

                    return (int)(min + (long)random.Next((int)count));



                // Inclusive Int32.MaxValue and the full signed range must not

                // overflow. Rejection avoids modulo bias; reuse the four bytes.

                const ulong domain = 1UL << 32;

                ulong limit = domain - domain % (ulong)count;

                uint sample;

                do

                {

                    random.NextBytes(randomRangeBytes);

                    sample = BitConverter.ToUInt32(randomRangeBytes, 0);

                } while (sample >= limit);

                return (int)(min + (long)(sample % (ulong)count));

            }

        }

Clone this wiki locally