-
Постов
3 295 -
Зарегистрирован
-
Посещение
-
Победитель дней
6
Тип контента
Профили
Новости
Статьи
Мемы
Видео
Форумы
Блоги
Загрузки
Магазин
Галерея
Весь контент YourBunnyWrote
-
Обратись к разрабам браузера. Похоже, проблема на их стороне.
-
Ну и слава яйцам. Качать эту чепуху с мобильного смерти подобно. Я бы вообще до 3 Мб ограничение поставил. Youtube, coub, vimeo в твоём распоряжении.
-
Исправлено.
-
Зачем?
- 1 339 ответов
-
- предложения
- пожелания
-
(и ещё 2 )
C тегом:
-
На странице файла в комментариях, автору в личку.
-
TESAll.Ru теперь доступен по протоколу HTTPS. Если столкнётесь с предупреждением браузера о незащищенном содержимом на страницах сайта, пожалуйста, сообщите об этом в специальной теме.
-
Исправлено.
-
Лучшие игровые движки и библиотеки на JavaScript
YourBunnyWrote прокомментировал
Kheruk новость в Железо и софтЧто одно, что второе уже либо вовсе не поддерживается, либо блокируется по умолчанию браузерами последние лет пять-семь. Кстати, во флеше, сюрприз-сюрприз, по сути тот же самый JS. -
Голосую за желтозубую бабку из ролика про Сашу ювелира.
-
Исправлено.
-
Если верить новостям, закрытые разделы галереи станут общедоступными после переезда.
- 1 339 ответов
-
- предложения
- пожелания
-
(и ещё 2 )
C тегом:
-
На сколько мы знаем, это не твой случай :girl_crazy:
- 1 339 ответов
-
- предложения
- пожелания
-
(и ещё 2 )
C тегом:
-
Статья «OBSE в Массы» специально для TESALL.RU Операторы Операторы присваивания := Присвоить += Прибавить и присвоить -+ Отнять и присвоить *= Умножить и присвоить /= Разделить и присвоить ^= Возвести в степень и присвоить Логические операторы || Логическое ИЛИ && Логическое И Строго меньше > Строго больше >= Больше или равно = Меньше или равно == Равно != Не равно ! Логическое отрицание (НЕТ) Математические операторы + Прибавление - Вычитание * Умножение / Деление % Остаток от деления ^ Возведение в степень Побитовые операторы >> Побитовый сдвиг влево Побитовый сдвиг вправо | Побитовое ИЛИ & Побитовое И ! Побитовое НЕТ Операторы для работы с данными :: Пара "ключ"::"значение" -> Оператор обращения к элементу массива Массив -> Элемент, тоже, что и Массив[Элемент]. $ Строка # Номер Оператор присваивания Для всех новых конструкций языка стоит использовать новый оператор присваивания Let вместо стандартного Set. Синтаксис: Let имя_переменной> := значение> Например: Let a := 10 Что эквивалентно: Set a to 10 Также можно использовать вместо знака присваивания знаки: прибавить и присвоить (+=), отнять и присвоить (-=), умножить и присвоить (*=), поделить и присвоить (/=), возвести в степень и присвоить (^=): Let a := 10 ; Set a to 10 Let b := 2 ; Set b to 2 Let c := a + b ; Set c to a + b ; c == 12 Let c += b ; Set c to c + b ; c == 14 Let c -= a ; Set c to c - a ; c == 4 Let c *= a ; Set c to c * a ; c == 40 Let c /= b ; Set c to c / b ; c == 20 Let c ^= b ; Set c to c ^ b ; c == 400 Проверка истинности В связи с тем, что некоторые новые конструкции языка, появившиеся с OBSE, некорректно работают со стандартными конструкциями, был введён новый оператор If. Так следующий фрагмент кода не будет работать: ScriptName SomeScript array_var SomeArr Begin GameMode Let SomeArr := ar_Construct Array Let SomeArr[0] := GetSelf If SomeArr[0] == Player ;… EndIf End Его стоит переписать следующим образом: ScriptName SomeScript array_var SomeArr Begin GameMode Let SomeArr := ar_Construct Array Let Arr[0] := GetSelf If Eval (SomeArr[0] == Player) ;… EndIf End Обработка исключений В OBSE существует оператор TestExpr, он служит для проверки исключений. Что такое исключение? Исключение - это события, приводящие к ошибке. Этим оператором стоит пользоваться, чтобы избежать ошибок в ходе работы скрипта. Например, к заранее непредвиденным ошибкам может приводить выход индекса массива за диапазон допустимых значений, продемонстрируем это в следующем примере: ScriptName SomeScript array_var Arr short Iterator Begin GameMode Let Arr := ar_Construct Array Let Arr[0] := 1 Let Arr[1] := 2 Let Arr[2] := 3 While Iterator 10 If TestExpr (Arr[Iterator]) Print ToString Arr[Iterator] Else Break Endif Let Iterator += 1 Loop End Операторы ToString и ToNumber Операторы ToNumber применяются для преобразования строк в числа и чисел в строки соответственно. Print ToString 10 ; Оператор ToString имеет сокращение: $ ; Следующая строка эквивалентна предыдущей Print $10 Оператор ToNumber и его сокращение # преобразовывает строку, содержащую численные символы, в численное значение. Let a += ToNumber "10" ; a == 10 Возможно преобразование строки, содержащей шестнадцатеричное значение, если она начинается с символов "0x" или установлен флаг bIsHex Let a += ToNumber "0xFF" ; a == 255 Let a += ToNumber "abc" 1 ; a == 2748 Оператор TypeOf Оператор TypeOf возвращает строку с типом данных. Возможные значения: "String" Строка "Number" Число "Form" Форма "Array" Индексный массив "Map" Вещественный массив "StringMap" Ассоциативный массив Операторы цикла В родном скриптовом языке Oblivion-а операторов цикла не существовало, по той простой причине, что сами скрипты выполняются довольно часто, и дополнительно зацикливаться на выполнении какого-либо участка кода не было нужды, но с появлением массивов и строковых переменных в OBSE оказалось невозможным обработать весь массив, например, за один проход. Понятие цикла не таит в себе ничего невероятного, это просто обусловленное циклическое повторение операторов замкнутых в тело цикла. Обратите внимание на то, что в теле операторов цикла (это не касается операторов безусловного перехода) нельзя использовать ключевое слово Return. Операторы безусловного перехода Label Операторы безусловного перехода служат для управления ходом выполнением скрипта. Оператор Goto. Операторы безусловного перехода не являются операторами цикла по сути, но могут быть использованы с этой целью, поэтому они описаны в этой главе. ScriptName SomeScript Begin GameMode ; … Label 1 ; Метка 1 ; … Label 2 ; Метка 2 If ; Если что-то произошло ; Переходим к метке 1 Goto 1 Else ; Иначе – к метке 2 Goto 2 EndIf End Несмотря на то, что операторы безусловного перехода являются несложной конструкцией, их использование не рекомендовано и требует повышенного внимания. Сами по себе безусловные переходы не есть ошибками с точки зрения выполнимости кода, но неправильное их использование может приводить к неявным ошибкам и неточностям в работе скрипта, в частности, к зацикливанию. Пожалуй, стоит упомянуть, что операторы RestoreIP соответственно, какие из них и в какой комбинации использовать – зависит только от вас. Цикл с предусловием While Синтаксис: ScriptName SomeScript Begin GameMode While ; Условие ; Тело цикла Loop End Последовательность операторов заключённая в теле цикла будет выполняться до тех пор, пока условие будет истинным. Следующий скрипт просто выводит в консоль числа от одного до десяти. ScriptName SomeScript short i Begin GameMode While i 10 Let i += 1 Print ToString i Loop End Цикл перебора массивов ForEach Оператор ForEach специально предназначен для перебора массивов, строк и содержимого контейнеров элемент за элементом. За каждый проход цикла переменная-итератор получает значение следующего элемента итерируемой переменой. В случае с контейнерами переменная-итератор должна иметь тип ref. За каждый проход цикла она будет получать значение ссылки на следующий объект выбранного контейнера. Следующий скрипт находит количество непустых камней душ в инвентаре игрока. ScriptName GetPlayerSoulGemCount ref Iterator short SoulGemCount Begin ScriptEffectStart ForEach Iterator - GetSelf If Iterator.IsSoulGem && Iterator.GetSoulLevel > 0 Let SoulGemCount += Iterator.GetRefCount EndIf Loop Print ToString SoulGemCount End Если цикл используется для перебора массивов, то переменная-итератор должна быть типа array_var. За каждый проход цикла два элемента массива-итератора (переменной-итератора), "key" и "value" получают следующую пару значений «ключ – значение» итерируемого массива. ScriptName ArrayForEachScript array_var Arr array_var StrMp array_var Mp array_var Iterator Begin ScriptEffectStart Let Arr := ar_Construct Array ; Arr – индексный массив Let StrMp := ar_Construct StringMap ; StrMp – ассоциативный массив Let Mp := ar_Construct Map ; Mp – вещественный массив ; ---------------------------------------------------------------------- Let Arr[0] := 100500 Let Arr[1] := 100501 Let Arr[2] := 100502 ForEach Iterator - Arr ; Первый проход скрипта ; Iterator["key"] == 0 Ключ ; Iterator["value"] == 100500 Значение ; Второй проход скрипта ; Iterator["key"] == 1 Ключ ; Iterator["value"] == 100500 Значение ; Третий проход скрипта ; Iterator["key"] == 2 Ключ ; Iterator["value"] == 100500 Значение Loop ; ---------------------------------------------------------------------- Let StrMp["Elem0"] := 100500 Let StrMp["Elem1"] := 100501 Let StrMp["Elem2"] := 100502 ForEach Iterator - StrMp ; Первый проход скрипта ; Iterator["key"] == "Elem0" Ключ ; Iterator["value"] == 100500 Значение ; Второй проход скрипта ; Iterator["key"] == "Elem1" Ключ ; Iterator["value"] == 100500 Значение ; Третий проход скрипта ; Iterator["key"] == "Elem2" Ключ ; Iterator["value"] == 100500 Значение Loop ; ---------------------------------------------------------------------- Let Mp[0.15] := 100500 Let Mp[3.14] := 100501 Let Mp[6.21] := 100502 ForEach Iterator - Mp ; Первый проход скрипта ; Iterator["key"] == 0.15 Ключ ; Iterator["value"] == 100500 Значение ; Второй проход скрипта ; Iterator["key"] == 3.14 Ключ ; Iterator["value"] == 100500 Значение ; Третий проход скрипта ; Iterator["key"] == 6.21 Ключ ; Iterator["value"] == 100500 Значение Loop End При переборе строковых переменных, переменная-итератор должна быть типа string_var. За каждый проход скрипта переменная-итератор будет получать значение каждого последующего символа итерируемой строковой переменой. Длина переменной-итератора - всегда один символ. Для примера составим небольшой скрипт, который будет искать заданное слово в строке. ScriptName StringForEachScript string_var Source ; Строка-источник, в ней и будем искать слово. ; Итерируемая переменная. string_var Iterator ; Переменная-итератор string_var Tmp ; Промежуточная переменная string_var Valid ; Искомая строка. Begin GameMode ; Задаём значение строке, в которой будем искать слово. Let Source := "Honey, I'm home." ; Задаём значение строке, которую будем искать. Let Valide := "home" ForEach Iterator - Source ; Если найдём в строке символ пробела, или символы пунктуации If Eval (Iterator == " " || Iterator == "," || Iterator == "." ) ; Очистим промежуточную строку и sv_Destruct Tmp ; пропустим текущую фазу цикла. Continue ; Иначе Else ; Будем наращивать промежуточное значение символами из строки-источника. Let Tmp += Iterator EndIf ; Как только найдём то, что искали - If Eval (Tmp == Valid) ; - скажем об этом Print Valid + "was found" ; и прервём цикл. Break EndIf Loop End Операторы Break и Continue Эти операторы используются в теле операторов цикла и служат для прерывания всего цикла или только текущей фазы, соответственно. Возможно, сначала не совсем понятно, для чего они нужны, но давайте посмотрим на конкретном примере. ScriptName SomeScript short Var Begin GameMode ; Зацикливаем : условие всегда истинно (бесконечный цикл) While 1 ; Давайте выведем в консоль только парные числа: от двух до двадцати ; Увеличиваем значение переменной на единицу Let Var += 1 ; Если значение нашей переменной превысило 20 - If Var > 20 ; - прерываем цикл. Break EndIf ; Проверяем парность значения переменной If Var % 2 != 0 ; Если число непарное – прерываем текущую фазу цикла и переходим к следующей. ; Все последующие операторы в теле цикла не будут выполнены в этой фазе. Continue EndIf ; Выводим значение переменной в консоль Print ToString Var Loop End Массивы и строки В OBSE появилось два принципиально новых типа данных, это массивы (array_var) и строковые переменные (string_var). Массивы являются неотъемлемым элементом любого языка программирования, так как представляют собою очень удобную и гибкую систему управления данными. Теперь они доступны и скриптерам для игры TES IV: Oblivion и серии игр Fallout 3. Что такое массивы? Массив – это область хранения данных, объединенная под общим именем. Доступ к элементам массива осуществляется по ключу. В зависимости от того, что представляет собою ключ, массивы делятся на индексные, вещественные и ассоциативные. Основными характеристиками массива есть его имя и размер. Массивы могут быть одномерными и многомерными, но, в основном, используются только одно-, двух- и реже трёхмерные массивы. Индексные массивы Массив, ключами элементов которого есть множество натуральных чисел, включая ноль, называется индексным. Для создания индексного массива следует вызвать функцию ar_Construct с аргументом Array: ScriptName ArrayExample array_var SomeArr Begin GameMode Let SomeArr := ar_Construct Array ; Теперь SomeArr – индексный массив End Теперь массив стал доступным для работы. Можем присваивать значение его элементам, умножать, делить, в общем обращаться как с обычными переменными. ScriptName ArrayExample array_var Arr1 Begin GameMode Let Arr1 := ar_Construct Array Let Arr1[0] := "Этому элементу присвоено строковое значение" Let Arr1[1] := 107 End Индексные массивы лучше подходят для использования в автоматизированных процессах, поскольку намного проще оперировать численными значениями ключей элементов массива. Для примера рассмотрим следующий скрипт, который создаёт десять элементов массива, присваивая им точно такие значения, будем использовать уже знакомый нам цикл While: ScriptName SomeScript array_var Arr short Tmp Begin GameMode Let Arr := ar_Construct Array While Tmp 10 Let Arr[Tmp] := Tmp Let Tmp += 1 Loop End Значение переменной Tmp меняется в диапазоне от нуля до девяти. В цикле создаются десять элементов массива, которым присваивается текущее значение переменной. Если вывести по порядку содержимое массива Arr, то мы увидим следующее: 0 1 2 3 4 5 6 7 8 9 Как я уже говорил раньше, но, возможно, вы не поняли, отсчёт элементов индексных массивов всегда следует начинать с нуля. Т.е. первый элемент всегда нулевой, второй – первый, и так далее. Let Arr1 := ar_Construct Array Let Arr1[0] := 100500 ; Это правильная последовательность Let Arr1[1] := 100501 ; задания значения элементам массива Let Arr1[2] := 100502 ; … ; -------------------------------------------------------- Let Arr2 := ar_Construct Array Let Arr2[1] := 1 ; Это неправильная последовательность! Let Arr2[2] := 2 ; Элементы с индексами 1, 2, 3 не могут Let Arr2[3] := 3 ; существовать, так как элемент с ; индексом 0 не существует Стоит помнить, что в OBSE массивы безразмерные, т.е. нет необходимости заранее задавать размер массива и чётко его придерживаться в процессе написания, а в последующем и обеспечивать это в процессе выполнения скриптов, но нельзя допускать выход индекса за диапазон его допустимых значений (размер массива). Как мы уже успели увидеть, элементы массивов могут принимать любое значение: целое, дробное, строковое и т.д. Ассоциативные массивы Массив, ключами элементов которого есть строковые константы, называется ассоциативным. Для создания ассоциативного массива следует вызвать функцию ar_Construct с аргументом StringMap: ScriptName ArrayExample array_var SomeArr Begin GameMode Let SomeArr := ar_Construct StringMap ; SomeArr – ассоциативный массив End Давайте создадим несколько элементов ассоциативного массива: ScriptName ArrayExample array_var SomeArr ref this Begin GameMode Let SomeArr := ar_Construct StringMap ; SomeArr – ассоциативный массив Let SomeArr["Reference"] := this := GetSelf Let SomeArr["Name"] := this.GetName Let SomeArr["Health"] := this.GetAV Health End В случае ассоциативного массива совершенно не важна последовательность ключей массива. Запомните, что ключом ассоциативного массива в OBSE может быть только строковая константа, применение индексов недопустимо! Во всех остальных отношениях индексные и ассоциативные массивы одинаковы. Ассоциативные массивы, безусловно, проще с точки зрения человеческого восприятия, но ими сложнее манипулировать в автоматизированных операциях программ, опять же, с точки зрения нашего восприятия. Вещественные массивы Вещественные массивы ранее никогда не встречались мною ни в одном языке программирования, с которым приходилось работать, да и при подготовке этого учебника мне не удалось найти что-то подобное в литературе, поэтому я взял на себя право дать им такое название исходя из их сущности и, конечно, моего мнения. Если где ошибся – поправьте. Итак. Вещественным массивом будем назвать массив, ключами элементов которого есть множество вещественных чисел. Для вещественных массивов не важен порядок ключей, как для индексного массива. Создаётся вещественный массив функцией ar_Construct с аргументом Map. ScriptName ArrayExample array_var SomeArr Begin GameMode Let SomeArr := ar_Construct Map ; SomeArr – вещественный массив Let SomeArr[3.14] := 100500 Let SomeArr[5 ^ (-1 / 2)] := "trololo" End Как видите, число π допустимый ключ вещественного массива. Да что там, как вы можете себе представить элемент с ключом 1/√5 ? Элементарно! Ну вот, теперь можете ощущать простор для экспериментов в ваших работах. Если, а главное – для чего, вы будете использовать вещественные массивы – решите сами. Многомерные массивы До этого момента мы были знакомы только с одномерными массивами. Мы уже слегка коснулись темы размерности массивов на начале этой главы, теперь рассмотрим этот вопрос более подробно. Механизм создания многомерного массива в OBSE несколько отличается от подобной процедуры в большинстве из языков программирования, если вам приходилось ранее быть знакомым с каким-либо из них. Для увеличения размерности массива от выбранного элемента следует присвоить ему значение типа array_var, т.е. создать массив в массиве. Давайте посмотрим на примере, так будет понятнее: ScriptName ArrayExample array_var Arr Begin GameMode Let Arr := ar_Construct Array Let Arr[0] := ar_Construct Array Let Arr[0][0] := 1 Let Arr[0][1] := 2 Let Arr[0] := ar_Construct Array Let Arr[0][0] := 1 Let Arr[0][1] := 2 End Получается, что мы сначала создали массив Arr, потом его нулевой элемент тоже сделали массивом. Нулевому элементу уже массива Arr[0] присвоили значение 1, а его первому элементу – значение 2. Затем тоже самое мы проделали с первым элементом массива Arr… Делаем всё точно также, если хотим создать трёхмерный и массив больших размерностей. Из такого принципа построения массивов следует, что: Элемент индексного массива может быть ассоциативным или вещественным массивом, и наоборот: ScriptName ArrayExample array_var Arr Begin GameMode Let Arr := ar_Construct Array Let Arr[0] := ar_Construct StringMap Let Arr[0]["SomeElem"] := 1 Let Arr[0]["OtherElem"] := 2 End Массив может иметь неодинаковую размерность в направлении любого из своих элементов ScriptName ArrayExample array_var Arr Begin GameMode Let Arr := ar_Construct Array Let Arr[0] := ar_Construct Array Let Arr[0][0] := ar_Construct Array Let Arr[0][0][0] := 36.6 Let Arr[0][1] := "ololo" Let Arr[1] := Player End Строковые переменные Строковые перемененные имеют тип string_var. До семнадцатой версии OBSE требовалось определять строковые переменные при помощи функции sv_Construct, подобно массивам, но теперь делать этого не нужно. ScriptName StringVarExample string_var Str Begin GameMode Let Str := "Это значение строковой переменной" End К значению строковой переменной всегда можно прибавлять значение другой строковой переменной или строковой константы. ScriptName StringVarExample string_var Str1 string_var Str2 Begin GameMode Let Str1 := "Это значение одной строковой переменной" Let Str2 := "Это значение другой строковой переменной." Let Str1 += ". " + Str2 Print Str1 ; Str1 == "Это значение одной строковой переменной. Это значение другой строковой переменной." End К элементам строковых переменных можно обращаться так же, как и к элементам одномерного индексного массива. Каждый элемент строки есть один её символ. Let Str := "Привет" ; Str[0] == "П" ; Str[1] == "р" ; Str[2] == "и" ; Str[3] == "в" ; Str[4] == "е" ; Str[5] == "т" Изменение значения элемента строковой переменной приводит к его замене. В случае если мы заменяем один элемент более длинной строкой, то её значение просто подставляется в заменяемую строку начиная с выбранного положения. Let Str := "Здесь что-то написано" ; ^ ^ ; 0 5 Let Str[5] := " может быть " ; Str == "Здесь может быть что-то написано" Массивы строк Массивы строк – обычный массив, может быть индексным, строковым или вещественным, произвольной размерности, элементу которого присвоено значение строковой переменной или строковой константы. ScriptName ArrayOfString array_var Arr string_var Str Begin GameMode Let Arr := ar_Construct Array Let Str := "Hello" Let Arr[0] := Str ; Arr[0][0] == "H" ; Arr[0][1] == "e" ; Arr[0][2] == "l" ; Arr[0][3] == "l" ; Arr[0][4] == "o" End Диапазоны элементов Диапазоны элементов доступны для массивов и строк. Для того чтобы задать диапазон элементов массива или строки, стоит написать их индексы через двоеточие: слева – стартовый индекс, справа – конечный. В случае с массивами вызов диапазона элементов создаёт их копию: ScriptName ArrayRange array_var Arr1 array_var Arr2 Begin GameMode Let Arr1 := Arr2 := ar_Construct Array Let Arr1[0] := 1 Let Arr1[1] := 2 Let Arr1[2] := 3 Let Arr1[3] := 4 Let Arr1[4] := 5 Let Arr2 := Arr1[1:3] ; Arr2[0] == 2 ; Arr2[1] == 3 ; Arr2[2] == 4 Let Arr1[0] := Arr1[0:4] ; Arr1[0][0] == 1 ; Arr1[0][1] == 2 ; Arr1[0][2] == 3 ; Arr1[0][3] == 4 ; Arr1[0][4] == 5 End В случае со строками, вызов диапазона создаст подстроку от стартового до конечного элемента. ScriptName StringRange string_var Str Begin GameMode Let Str := "Здесь что-то написано" ; ^ ^ ^ ^ ^ ^ ; 0 4 6 11 13 20 Print Str[0:4] ; Здесь Print Str[6:11] ; что-то Print Str[13:20] ; написано ; ---------------------------------------------------------------------- Let Str := "Это строковая переменная" ; ^ ^ ^ ^ ^ ^ ; 0 2 4 12 14 23 Let Str[4:23] := "СПАРТА!!!" ; Str == "Это СПАРТА!!!" End Пользовательские функции Что такое функция? В программировании, функция – это именуемая часть программы, которая непосредственно не выполняется, но доступна из любой части программы, в том числе и для самой себя, которая может инициировать её выполнения посредствам обращения (вызова) с передачи ей начальных параметров (аргументов функции). По окончании выполнения функция возвращает результат (значение функции) вызвавшей её части программы. Функция, которая не предусматривает возвращение результатов (не имеет значения), называется процедурой. Вызов функцией самой себя называется рекурсией. Функция, которая в качестве аргументов принимает значение другой функции непосредственно, называется суперпозицией. Не столь важное понятие в программировании, но привожу для общего развития. Функция – очень удобный механизм разделения типичных, востребованных программных действий делающий их доступным любому скрипту вашего плагина. Пользовательские функции Для того, чтобы создать функцию, следует создать новый скрипт. Имя скрипта – это имя функции. На то, что этот скрипт есть функцией, указывает ключевое слово Function, которое используется в качестве типа блока с ключевым словом Begin. В скрипте функции может находиться только один блок Begin – End и только типа Function. Аргументы функции перечисляются в системных скобках, за ключевым словом Function, через запятую. Функция в OBSE может иметь до десяти аргументов, или не иметь их вовсе. Все аргументы функции – переменные, объявляются как в обычном скрипте. Значение функции определяется ключевым словом SetFunctionValue. Значением функции может служить как константа, так и переменная. Возврат из функции, имеющей или не имеющей значения, выполняется ключевым словом Return. Возврат из функции означает прекращение её выполнения. Помните, нельзя использовать Return в циклах! ScriptName FunctionName ; Имя функции type arg1 ; Первый аргумент функции type arg2 ; Второй аргумент функции … type arg10 ; Десятый аргумент функции type RetVal ; Значение функции Begin Function {arg1, arg2, …, arg10} ; … SetFunctionValue RetVal ; Определение значения функции Return ; Возврат из функции End Для примера составим функцию, суммирующую два числа. ScriptName Sum float Num1 ; Первое число float Num2 ; Второе число Begin Function {Num1, Num2} Let Num1 += Num2 ; Находим сумму чисел SetFunctionValue Num1 ; Задаём возвращаемое значение Return ; Возвращаем результат End Для вызова пользовательской функции нужно использовать ключевое слово Call. ScriptName SomeScript float Var Begin GameMode ; Вызываем только что созданную намии функцию Let Var := Call Sum 10 20 ; Var == 30 End Как я уже говорил ранее, не все функции обязательно должны иметь аргументы и/или возвращать значение. Давайте составим пример такой функции, она будет просто добавлять сто Септимов в карман игрока. ScriptName ProcedureExample Begin Function {} Player.AddItem Gold001 100 End В OBSE существует функция, которая позволяет определить скрипт (функция возвращает ссылку на него), из которого произошёл вызов функции, она называется GetCallingScript. ScriptName GetCallingScriptExample Begin Function {} If GetCallingScript == MyQuestScript SetFunctionValue 1 Else SetFunctionValue 0 EndIf Return End Функция GetCallingScript ничего не возвращает, если вызов функции произошёл без помощи оператора Call, или функция была использована как обработчик события. Обработчики событий Понятие заимствованное из .NET языков программирования. Обработчики событий являются функциями, которые автоматически вызываются программой, если происходит определённое событие. Все события в OBSE предопределены, с большинством из них вы должны быть уже знакомы, если ранее вам уже приходилось писать скрипты на родном скриптовом языке Oblivion-а. OnHit Цель:ref Атакующий:ref Происходит при нанесении атакующим урона цели OnHitWith Цель:ref Оружие:ref Происходит при нанесении оружием урона цели OnMagicEffectHit Цель:ref Магический_эффект:string (четырёхсимвольный код) Происходит при наложении магического эффекта на цель OnActorEquip Цель:ref Предмет:form Происходит при надевании предмета целью OnDeath Цель:ref Убийца:form Происходит при смерти цели OnMurder Цель:ref Убийца:form Происходит при убийстве цели убийцей OnKnockout Цель:ref Происходит при нокаутировании цели OnActorUnequip Цель:ref Предмет:form Происходит при снятии предмета целью OnAlarm Trespass Заметивший:ref Нарушитель:ref Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил взлом. OnAlarm Steal Заметивший:ref Нарушитель:ref Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил кражу. OnAlarm Attack Заметивший:ref Нарушитель:ref Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил нападение. OnAlarm Pickpocket Заметивший:ref Нарушитель:ref Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил карманную кражу. OnAlarm Murder Заметивший:ref Нарушитель:ref Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил убийство. OnPackageChange Цель:ref Пакет:form Происходит при смене целью AI пакета OnPackageStart Цель:ref Пакет:form Происходит при старте целью AI пакета OnPackageDone Цель:ref Пакет:form Происходит при завершении целью AI пакета OnStartCombat Цель:ref Опонент:ref Происходит, когда цель нападает на опонента OnActivate Активатор:ref Цель:ref Происходит, когда цель активирует активатор OnVampireFeed NONE Происходит, когда вампир перестаёт питаться OnSkillUp Код_навыка:int Происходит при повышении навыка игрока OnScriptedSkillUp skillActorValueCode:int amount:int Происходит перед изменением навыка игрока скриптовой командой OnDrinkPotion Цель:ref Зелье:form Происходит, когда цель принимает зелье OnEatIngredient Цель:ref Ингридиент:form Происходит, когда цель съедает ингридиент OnActorDrop Цель:ref Предмет:ref Происходит, когда цель выбрасывает/роняет предмет OnSpellCast Цель:ref Заклинание:form Происходит, когда цель произносит заклинание OnScrollCast Цель:ref свиток:form Происходит, когда цель читает заклинание со свитка OnFallImpact Цель:ref Происходит, когда цель упадёт с опасной высоты, перед тем, как получить повреждение OnMapMarkerAdd Маркер:ref Происходит при добавлении маркера на карту игрока OnHealthDamage Величина_повреждения:float Атакующий:ref Происходит перед тем, как актёр получит повреждение. Если актёр свалится с высоты, то аргумент «Атакующий» будет иметь нулевое значение. Для определения актёра получившего повреждение стоит использовать функцию GetSelf. OnCreateSpell Заклинание:ref Происходит, когда игрок создаёт новое заклинание OnCreatePotion Зелье:ref Уникальное_ли:int Происходит, когда игрок приготовит новое зелье. Второй аргумент будет равен 1, если игрок впервые приготовил такое зелье, иначе он будет равен 0. OnEnchant Предмет:ref Происходит, когда игрок зачаровывает предмет. OnAttack Цель:ref Происходит, когда цель начинает проигрывать анимацию атаки или наложения заклинания. OnBowAttack Цель:ref Происходит, когда цель начинает проигрывать анимацию стрельбы из лука. OnRelease Цель:ref Происходит, когда цель заканчивает проигрывать анимацию атаки, стрельбы или наложения заклятья. OnBlock Цель:ref Происходит, когда цель начинает проигрывать анимацию блокирования ударов. OnRecoil Цель:ref Происходит, когда цель начинает проигрывать анимацию получения отдачи. OnStagger Цель:ref Происходит, когда цель начинает проигрывать анимацию получения урона. OnDodge Цель:ref Происходит, когда цель начинает проигрывать анимацию уклонения от атаки. LoadGame Имя_файла:string Происходит при загрузке игры SaveGame Имя_файла:string Происходит при сохранени игры PostLoadGame Игра_загружена_удачно:bool Происходит после загрузки игры. Передаёт функции-обработчику события 1, если игра была загружена удачно, 0 - если нет ExitGame NONE Происходит при выходе из игры ExitToMainMenu NONE Происходит при выходе в главное меню QQQ NONE Происходит при выходе из игры посредствам вызова консольной команды QQQ OnNewGame NONE Происходит при старте новой игры Для того, чтобы задать обработчик события существует функция SetEventHandler, её синтаксис таков: (success:bool) SetEventHandler eventID:string functionScript:ref filter1:pair filter2:pair Где, eventID – имя события, одно из тех, которые наведены в таблице; functionScript – имя функция, которая будет использована для обработки события; filter1 – фильтр первого аргумента функции-обработчика; filter2 – фильтр второго аргумента функции-обработчика. Функция SetEventHandler возвращает единицу, если удалось назначить указанную функцию обработчиком события, или 0 – если нет. Аргументы filter1 и filter2 применяются для фильтрации аргументов передаваемых функции-обработчику события. Если их не задавать, то обработчику события будут передаваться все аргументы инициируемые определённым событием. Например, давайте составим функцию, которая будет использована для обработки события OnHit ScriptName OnHitHandlerExample ref Target ref Attacker Begin Function {Target, Attacker} Print Attacker.GetName + " attacked " + Target.GetName End И инициализируем её как обработчик события: ScriptName OnHitHandlerQuestScript Begin GameMode SetEventHandler "OnHit" OnHitHandlerExample End В таком случае, в ячейке, где разворачиваются игровые действия, на данный момент, любое событие OnHit инициализирует выполнение функции OnHitd] Если мы хотим, допустим, чтобы это событие выполнялось только когда атакуют игрока, следует установить фильтр первому аргументу, согласно описания события OnHit. ScriptName OnHitHandlerQuestScript Begin GameMode SetEventHandler "OnHit" OnHitHandlerExample "ref"::Player.GetSelf End Оператор :: создаёт пару "Ключ"::"Значение". Ключ должен иметь значение типа соответствующего аргумента согласно перечню событий. Не зависимо от того, что первый аргумент функции-обработчика теперь может принимать только одно значение и мы заведомо знаем об этом, функция-обработчик всёравно должна иметь два аргумента. Если мы хотим избавиться от обработчика события, следует использовать функцию RemoveEventHandler. Её синтаксис аналогичен функции SetEventHandler. ScriptName OnHitHandlerQuestScript Begin GameMode RemoveEventHandler "OnHit" OnHitHandlerExample End [p]Если у нас есть несколько обработчиков события OnHit, то вызов функции RemoveEventd] ScriptName OnHitHandlerQuestScript Begin GameMode SetEventHandler "OnHit" OnHitHandlerExample SetEventHandler "OnHit" OnHitHandlerExample "ref"::Player.GetSelf ; ---------------------------------------------------------------------- RemoveEventHandler "OnHit" OnHitHandlerExample ; Удалит все события OnHit ; ---------------------------------------------------------------------- RemoveEventHandler "OnHit" OnHitHandlerExample "ref"::Player.GetSelf ; Удалит события только с соответствующим фильтром End [p]С помощью функции GetCurrentEventName, вызванной из функции-обработчика события, можно узнать имя текущего события. Это полезно, если одна функция используется как обработчик нескольких событий. ScriptName MultiEventHandlerFunction ref Arg1 ref Arg2 Begin Function {Arg1, Arg2} If Eval (GetCurrentEventName == "OnHit") Print Arg2.GetName + " атаковал " + Arg1.GetName ElseIf Eval (GetCurrentEventName == "OnActorEquip") Print "Игрок " + Arg1.GetName + " одел " + Arg2.GetName EndIf End
-
Construction Set Extender - плагин для OBSE
YourBunnyWrote опубликовал статья в Модостроение Oblivion
Плагин для OBSE который, расширяет возможности стандартного редактора TES IV: ConstructionSet Скажите, кто из вас не мечтал, чтобы это ужасное окно редактора скриптов само проставляло табуляцию? Кому из вас не мешали в работе постоянные окошки с предупреждениями от конструктора? А не приходилось ли вам сталкиваться с тем, чтобы конструктор закрывался от одного вашего небрежного действия и ваша полуторачасовая работа летела коту под хвост? Так или иначе вы не сможете не оценить вклад автора этого замечательного плагина: shadeMe, за что ему респект и уважуха большой поклон. Нововведения Теперь можно загружать мастер-файлы в конструктор для редактирования Можно менять заголовочную информацию о мастер-файле: Улучшен инструмент «Поиск текста»: Дважды кликнув по выбранному результату поиска, откроется соответствующее окошко для его редактирования, или, если это ссылка на объект, то он загрузится в окне визуализатора. Теперь можно загружать плагины с отсутствующими мастер-файлами: Отныне все предупреждения не выскакиваю в диалоговых окнах, а тихо и мирно выводятся в консоль Быстрый выход из CS. Сохранения плагинов как мастер-файлов: Теперь плагин можно сохранить как ESM или как ESP, на выбор. Теперь диалоговое окно которое выскакивает при закрытии окна редактора скриптов с подтверждением о сохранении скрипта имеет кнопку "Отмена", что позволяет вернутся к редактированию скрипта, как, например, в Ворде. Улучшенная команда рекомпиляции скриптов: Теперь при вызове команды «Рекомпилировать все скрипты» они будут рекоплилированы только в активном плагине. Лог компиляции: Результаты рекомпиляции выводятся в консоль. Неизвестные записи и типы групп: Результаты рекомпиляции выводятся в консоль.Если при загрузке, в плагине, будут обнаружены неизвестные записи или типы групп, то это не вызовет ошибки и, как следствие, закрытие окна «Конструктора». Удвоен максимальный размер скомпилированного скрипта: Теперь размер байт-кода скомпилированного скрипта может быть равен 32KB. Ошибки компиляции: Теперь ошибки компиляции выводятся в соответствующую область окна редактора скриптов. Сохранение плагина при открытых окнах «Конструктора»: Теперь не обязательно закрывать все диалоговые окна перед сохранением плагина. BSA архивы больше не загружаются выборочно: Все BSA архивы в папке Data загружаются при старте «Конструктора». Установка Скачать плагин можно по ссылке в нашей базе. Для установки плагина извлеките содержимое плагина в папку Oblivion. Также рекомендуется скачать и распаковать в папку Oblivion архив CS 10 Executable, ссылка на который дана всё на той же странице. Затем откройте файлик ConstructionSet.ini, найдите в нём строку bAllowMultipleEditors и присвойте ей значение 1. Новый редактор скриптов Рис.1 Окно редактора скриптов Новый редактор полностью заменил старый и вплотную приблизился к редакторам кода в понимании современного человека, единственное, чего ему не хватает, на мой взгляд, так это подсветки синтаксиса, будем надеяться, что автор не забудет реализовать эту приятную мелочь в последующих версиях своего творения. Панель инструментов редактора скриптов - создать новую вкладку - создать новый скрипт. - открыть скрипт. Выбор скрипта Рис.2 Диалоговое окно для выбора скрипта Окошко для выбора загружаемого в редактор скрипта также стало более информативным, в перечне скриптов появилась колонка с типом скрипта, а также появился предпросмотр. Теперь можно загружать сразу несколько скриптов в редактор: к списку скриптов применимы уже привычные комбинации клавиш системы Windows - Shift и Control, внизу окошка, под перечнем скриптов, расположена текстовая строка которая служит для быстрого поиска по списку. - сохранить скрипт. - сохранить, но не компилировать. - сохранить и скрипт и активный плагин. - загрузить предыдущий по списку скрипт. - загрузить следующий по списку скрипт. - перекомпилировать все скрипты в активном плагине. - перекомпилировать зависимые скрипты. - удалить скрипт. - сохранить скрипты во всех открытых вкладках. - вызвать меню настроек. Меню настроек Рис.3,4,5,6,7 Меню настроек редактора скриптов Вкладка General Auto-Indent Script Lines ((рус.) "Авто сдвиг строк кода") - При включённой опции программа будет автоматически вставлять отступ (символ табуляции) после открытия и убирать его после закрытия следующих блоков: 0 Begin - End 0 If - ElseIf - EndIf 0 While - Loop 0 ForEach - Loop Show Editor As Child Window - если этот флажок установлен, то окно редактора скриптов будет открыто как дочерное окно главного окна CS. Вся разница заключается в том, что если этот пункт не отмечен, то открытое окно редактора скриптов будет занимать дополнительную вкладку в панели задач. Save Caret Position With Script - если этот флажок установлен, то программа будет сохранять положение курсора при переходе на новую строку таким же как оно было на начале предыдущей строки. Говоря простым языком, курсор не будет постоянно перепрыгивать на начало строки, как это было в стандартном редакторе. Close Editor With Last Tab ((рус.) "Закрыть редактор с последней вкладкой")- ну тут всё предельно ясно, когда мы закроем последнюю вкладку, то и окошко редактора закроется. - показать или спрятать область окна редактора скриптов, куда выводятся сообщения и ошибки при компиляции скриптов. - показать или спрятать область окна редактора скриптов, куда выводятся результаты поиска и замены в тексте скрипта. - показать или спрятать область окна редактора скриптов со списком закладок. - экспортировать текущий скрипт в текстовый документ - экспортировать все загруженные в редактор скрипты в текстовые документы (на один скрипт - один документ) - импортировать текст скрипта из текстового документа - импортировать текст скриптов из нескольких текстовых документов (из одного документа - один скрипт, каждый будет открыт в новой вкладке) - показать или спрятать список переменых используемых в текущем скрипте. - выделяет следующие блоки отступами для читаемости кода: Begin - End If - ElseIf - EndIf While - Loop ForEach - Loop - привязать скрипт к существующей или новой записи. Назначение скрипта Рис.8 Окно назначения скриптов В новом редакторе появилась возможность задавать скрипты существующим или новым записям в плагине, которые имеют поле "Скрипт". Для тог чтобы "прилепить" скрипт к существующей записи - просто выбираем её из разворачивающегося списка размещённого напротив переключателя Bind To Existing Form. Для того, чтобы создать новую форму - устанавливаем переключатель в позицию Bind To New Form, задаём тип, параметры и имя формы. Если вы всё сделали правильно, то будет создана новая форма с указанным именем указанного типа. Контекстное меню Copy Paste Find Toogle Comment - закомментировать выделеные строки Toogle Bookmark - создать закладку на выбранной строке Рис.9 Диалоговое окно вызванное командой Toogle Bookmark Add Message - команда позволяет написать сообщение самому себе, которое будет выведено... Кто Где бы вы думали? Волшебный кролик! Конечно же в области уведомлений, куда, например, выводит сообщения об ошибке программа при компиляции скриптов. Не знаю зачем shadeMe предусмотрел такую возможность, пожалуй он просто решил насадить лишнюю гайку на лишний болт. Рис.10 Диалоговое окно вызванное командой Add Message Copy To Edit Box - копирует текст в окошко расположенное в нижнем левом углу окна редактора скриптов. В разворачивающемся списке правее можно выбрать необходимое действие над этим фрагментом, как то искать, заменять и т.д. Look up on the Wiki Look up on the OBSE Dok Lookup on Google Препроцессор "Как в лучших домах Ландона и Порижа", — Остап Бендер. Ещё одно новшество в CSE. Препроцессор обрабатывает данные перед компиляцией, позволяя "скармливать" последнему (этому самому, компилятору, которому) только определённую часть кода в определённых ситуациях. А зачем он нужен? Тяжело объяснить козе зачем ей баян, но согласитесь, если она баянистка, то и вопросы как-то сами отпадают. Правда?! Но давайте будем конкретнее и рассмотрим пример "на кошечках": Кто делал сам, или разбирал чужие плагины, не трусы, разумеется, тот не мог не встретить закомментированные сообщения с отладочной информацией. Допустим у вас плагин в котором не пять и не десять скриптов, в каждом из которых сотня - полторы строк, каждый из которых должен быть отлажен. Доводя до конечного пользователя вся эта информация должна быть скрыта или вычещена. И тут вы понимаете что вам нужно перелопатить добрую тыщу строк в поисках своих месседжбоксов... А можно ли это как-то... малой кровью? Ну разумеется! К чему же я тогда веду?! Но для начала ознакомимся с самим командами препроцессора: Команды препроцессора Все команды препроцессора должны быть закомментированны, т.е. перед ними должна стоять точка с запятой (";"). Команды могут быть однострочными или многострочными, для отделения одних от других перед командой должен стоять символ "#" в случае, если это однострочная команда, или "@" - если многострочная. DEFINE - определяет константу Синтаксис: ;#DEFINE ИМЯ_КОНСТАНТЫ> значение_константы> Например следующая команда определяет константу с именем X и значением 3 1. ;#DEFINE X 3 Перед компиляцией скрипт будет пропущен через препроцессор, и всякий раз, как он встретит этот самый X, он заменит его на его значение, т.е. на 3. Например имеется следующий элементарный скрипт: ;#DEFINE X 3 ScriptName PreprocessorTestingScript short Y Begin GameMode Set Y to Y + X End Пропущенный через препроцессор он поступит на компиляцию уже в следующем виде: ScriptName PreprocessorTestingScript short Y Begin GameMode Set Y to Y + 3 End IMPORT - импортирует в то место, где стоит эта команда указанный скрипт, который находится в папке Oblivion\Data\Scripts\ Синтаксис: ;#IMPORT "Название_файла>" Название_файла> - это название текстового документа в папке Oblivion\Data\Scripts\ без расширения. Например в папке Oblivion\Data\Scripts\ лежит файлик с названием Part1.txt, пускай в нём написано: short a float b ref c А мы хотим засунуть его содержимое в наш скрипт. Пишем: ScriptName PreprocessorTestingScript ;#INCLUDE "Part1" Begin GameMode Set a to 10 Set b to .015 Set c to GetSelf End Получаем: ScriptName PreprocessorTestingScript short a float b ref c Begin GameMode Set a to 10 Set b to .015 Set c to GetSelf End ENUM - определяет перечисление Синтаксис: ;#ENUM { = = ... = } или ;@ENUM ;{ ; = ; = ; ... ; = ;} В следствии того, что элементы перечисления могут принимать только численные значения, то вся польза от этой конструкции исходит на нет. По сути перечисление (ENUM), в том виде, в котором мы имеем его здесь, является более громоздкой и менее гибкой формой определения (DEFINE). Вполне возможно что автор просто не довёл её до ума, т.к. даже в официальной документации ей посвящено всего пару строк. Да, и ещё очень важное замечание: между именем элемента перечисления, знаком равенства и значением не может быть пробелов, т.к. это вызывает ошибку. IF - условный оператор. Синтаксис: ;@IF () ;{ ; ;} В условии можно применять логические операторы: [==] - Равно [!=] - Не равно [>] - Строго больше [] - Строго меньше [>=] - Больше или равно [=] - Меньше или равно [&&] - Логическое И [||] - Логическое ИЛИ В следующем примере показано, как избавится от отладочной информации о которой мы говорили в начале: ;#DEFINE _DEBUG_MODE 1 ScriptName PreprocessorTestingScript ; ... Begin GameMode ; Многабукаф ;@IF(_DEBUG_MODE==1) ;{ ; Message "Debug mode is ON" ;} End Таким образом просто присвоив константе _DEBUG_MODE значение 0 и перекомпилировав скрипт мы избавимся от ненужных частей кода. Легко и просто. Редактор заметок Рис.11 Окно редактор заметок Редактор заметок позволяет сопровождать процесс разработки разнообразными комментариями, из которых можно ссылаться на записи плагина. Вы что-то делали, но были вынуждены это забросить на неопределённое время, потом вы об этом забыли... Теперь можно оставить себе напоминание. В левой области редактора заметок вызываем контекстное меню и выбираем пункт Add Tag и обзываем его как хотим. Для того чтобы прикрепить какой-то объект к записи в комментариях, нужно вызвать на нём контекстное меню в окне объектов и выбрать пункт Add To Active Tag. Чтобы вызвать редактор заметок, выберете пункт View -> Tag Browser в главном меню. Редактор ссылок Рис.12 Окно редактор ссылок Редактор ссылок позволяет комбинировано управлять свойствами объектов помещённых в загруженную ячейку. Ничего принципиально нового тут нет, по этому особо на этом не останавливаемся. Чтобы вызвать редактор ссылок, выберете пункт World -> Batch Edit References в главном меню. Информация о файле плагина Рис.13 Окно информации о плагине Находится в Gameplay -> Use Info Listing. Тут можно более подробно ознакомится со всеми записями в плагине и проследить их связи. Консоль Рис.14 Окно консоли Отныне программа выводит лог в консоль, благодаря этому элементу исчезли многочисленные навязчивые окна с предупреждением от "Конструктора". Также существует несколько консольных команд. Консольные команды LoadPlugin - загружает указанный плагин. Синтаксис: LoadPlugin string: bool:SetAsActive Где plugin_name.extension - название плагина, SetAsActive - Указывает, сделать ли загружаемый плагин активным. 1 - если ДА, 0 - если НЕТ. LoadForm - открывает соответствующее окно для редактирования указанной формы. Синтаксис: LoadForm string: SavePlugin - сохраняет плагин. Команда без параметров. AutoSave - делает резервную копию плагина в каталог Data\Backup\. Команда без параметров. Exit - Выход из "Конструктора". Команда без параметров. Настройки CSE Панель настроек CSE (рис.15) находится в главном меню File -> CSE Preferences. Редактировать настройки CSE можно как с помощью этой панели, так и вручную через файл \Oblivion\Data\OBSE\Plugins\Construction Set Extender.ini. Далее привожу список параметров: Рис.15 Окно настроек CSE Относится к Имя За что отвечает Консоль Top Растояние от верхнего края экрана Консоль Left Растояние от левого края экрана Консоль Right Растояние от правого края экрана Консоль Bottom Растояние от нижнего края экрана Консоль LogCSWarnings Выводить ли лог ошибок "Конструктора" в консоль? 1 - ДА; 0 - НЕТ. Консоль LogAssertions Выводить ли сообщений ошибок "Конструктора" в консоль? 1 - ДА; 0 - НЕТ. Консоль HideOnStartup Прятать ли окно консоли при запуске? 1 - ДА; 0 - НЕТ. Консоль ConsoleUpdatePeriod Время обновления консоли в миллисекундах CSE LoadPluginOnStartup Загружать ли плагин указанный в поле StartupPluginName при старте конструктора автоматически? 1 - ДА; 0 - НЕТ. CSE StartupPluginName Название файла плагина, который будет загружен при старте конструктора, если установлен параметр LoadPluginOnStartup CSE OpenScriptWindowOnStartup Открывать ли окно редактора скриптов при старте конструктора автоматически? 1 - ДА; 0 - НЕТ. CSE StartupScriptEditorID Название скрипта, который будет открыт в о редакторе скриптов при старте "Конструктора". Трубует включённого параметра OpenScriptWindowOnStartup CSE ShowNumericEditorIDWarning CSE SetWorkspaseOnStartup Выбрать рабочей директорию заданую параметром DefaultWorkspasePath? 1 - ДА; 0 - НЕТ. CSE DefaultWorkspasePath Путь к рабочей директории Визуализатор UpdatePeriod Время обновления окна визуализатора в миллисекундах Визуализатор DisplaySelectionStats Выводить информацию о выбранном объекте в окне визуализаторы? 1 - ДА; 0 - НЕТ. Визуализатор UpdateViewPortAsync Разрешить обновление картинки в окне визуализатора, если оно не активно? 1 - ДА; 0 - НЕТ. -
Вопрос явно задан не в том месте. Ищите в разделах по соответствующим играм.
- 1 339 ответов
-
- предложения
- пожелания
-
(и ещё 2 )
C тегом:
-
Потому что куча картинок в постах со сторонних сайтов прикручены по HTTP.
- 1 339 ответов
-
- предложения
- пожелания
-
(и ещё 2 )
C тегом:
-
Кэш очистить попробуй.
-
Поправил.
-
Ctrl+Shift+Delete или перейти по ссылке chrome://settings/clearBrowserData
-
Она не для красоты, она для устрашения.
-
Кэш чистил?
-
Ешь вода, пей вода - срать не будешь никогда. Фу, и правда как-то некрасиво.
-
Мы тут не при чём. Проблема исправлена.
-
Зачем? Там есть ответы других участников.
- 1 339 ответов
-
- предложения
- пожелания
-
(и ещё 2 )
C тегом: