Repository navigation
UO Topic files json data
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
Головна · C# · IDE · Команди UO · За абеткою · Приклади · Мови
Робота з файлами, JSON, масивами та колекціями. У C# можна використовувати стандартні класи .NET; у цьому розділі зібрано допоміжні команди UO для роботи з даними.
| Тема | Команди та пояснення |
|---|---|
| Файли | C# та стандартна бібліотека |
| Розбір JSON | C# та стандартна бібліотека |
| Читання JSON із файлу | C# та стандартна бібліотека)) |
| Збереження JSON у файл | C# та стандартна бібліотека |
| Перетворення на текст JSON | C# та стандартна бібліотека |
| Списки | C# та стандартна бібліотека |
| Словники | C# та стандартна бібліотека |
| Масиви | C# та стандартна бібліотека · C# та стандартна бібліотека |
| Потік у пам’яті | C# та стандартна бібліотека |
UO.GetArrayLength · UO.GetWord · UO.GetWordCount
C# та стандартна бібліотека · C# та стандартна бібліотека · C# та стандартна бібліотека
Нижче наведено короткі приклади. У повному описі кожної команди є параметри, результат, обмеження та кілька самостійних скриптів: прямий код, варіант із функцією та варіант із класом.
Параметри, результат та всі сценарії
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;Параметри, результат та всі сценарії
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;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.GetArrayLength(object? arg);Вважає безпосередні осередки масиву для обмеженого перебору та безпечного читання індексу.
int >= 0. Порожній Array та значення іншого виду дають 0: тільки за результатом не можна перевірити тип. Це кількість, а не bool і останній індекс.
- Локальна перевірка: не надсилає запит серверу, не переміщує предмети та не змінює масив. У прикладах подано навчальні дані, а не живий інвентар.
- Перевіряє вигляд значення та читає Array.Length без обходу та підсумовування. оголошення змінної values(2) створює три осередки, індекси 0..2, включаючи незаповнені.
- Вкладені елементи рекурсивно не рахуються. Для рядка є Len, для List/Dictionary - їх Count. UO.GetArrayLength - сумісне ім'я тієї ж локальної перевірки.
Кожен приклад можна зберегти окремим файлом .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));Параметри та порядок виконання:
- оголошення змінної 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;Параметри та порядок виконання:
- У 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;
}Параметри та порядок виконання:
- Рядок дає 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.
Параметри: arg (Any)
Результат: dynamic / Any.
Під час виклику:
Внутрішній код реалізації, не самостійний скрипт.
public static InjectionValue GetArrayLength(InjectionValue arg) => arg.Kind==InjectionValueKind.Array?new InjectionValue(arg.Array.Length):InjectionValue.Zero;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
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
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.GetWord("red green blue", 1);
UO.Print("GetWord: " + Convert.ToString(result));Параметри та порядок виконання:
- 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;Параметри та порядок виконання:
- 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, "|");
}Параметри та порядок виконання:
- 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.
Параметри: value (String), wordIndex (Integer)
Результат: string / String.
Під час виклику:
-
InjectionScript.Runtime.InjectionApi.GetWord. -
InjectionScript.Runtime.InjectionApi.GetWord:GetWord(value,wordIndex," ").
Внутрішній код реалізації, не самостійний скрипт.
private static string GetWord(string value,int wordIndex) => GetWord(value,wordIndex," ");Параметри: value (String), wordIndex (Integer), delimiter (String)
Результат: string / String.
Під час виклику:
-
InjectionScript.Runtime.InjectionApi.GetWord. -
InjectionScript.Runtime.InjectionApi.SplitWords:SplitWords(value,delimiter).
Внутрішній код реалізації, не самостійний скрипт.
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;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
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
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.GetWordCount("red green blue");
UO.Print("GetWordCount: " + Convert.ToString(result));Параметри та порядок виконання:
- 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;Параметри та порядок виконання:
- 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;Параметри та порядок виконання:
- 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.
Параметри: value (String)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApi.GetWordCount. -
InjectionScript.Runtime.InjectionApi.GetWordCount:GetWordCount(value," ").
Внутрішній код реалізації, не самостійний скрипт.
private static int GetWordCount(string value) => GetWordCount(value," ");Параметри: value (String), delimiter (String)
Результат: int / Integer.
Під час виклику:
-
InjectionScript.Runtime.InjectionApi.GetWordCount. -
InjectionScript.Runtime.InjectionApi.SplitWords:SplitWords(value,delimiter).
Внутрішній код реалізації, не самостійний скрипт.
private static int GetWordCount(string value,string delimiter) => SplitWords(value,delimiter).Length;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
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 можуть повернути різні значення. Команда не перевіряє, чи допустима обрана клітина для руху або перенесення: це перевіряє відповідна ігрова команда.
Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.
Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.
Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.
var result = UO.Random(10);
UO.Print("Random: " + Convert.ToString(result));Параметри та порядок виконання:
- 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));Параметри та порядок виконання:
- 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;
}Параметри та порядок виконання:
- 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;
}Параметри та порядок виконання:
- Перший 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));Параметри та порядок виконання:
- В обох викликах 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;
}Параметри та порядок виконання:
- У 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;
}
}Параметри та порядок виконання:
- 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.
Параметри: max (Integer)
Результат: int / Integer.
Під час виклику:
Внутрішній код реалізації, не самостійний скрипт.
public int Random(int max)
{
lock (randomSync) return random.Next(max);
}Параметри: 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));
}
}ClassicUO — Bad Newbie & C# Scripts IDE