Мih@ » 22-07-2008 09:04:49

Побыв прошлую ночь в культурном шоке от темы "Учебник по скриптированию" и так не сумев её отредактировав, оставив хоть какую-нибудь часть в изначальном виде, решил всё-таки выложить хотя бы то, что есть. И что есть уже довольно-таки давно. )
________________________________________________________________________________

1. Общая информация

1.1. О скриптах

1.1.1. Что такое скрипты, для чего они нужны?
Это командные сценарии, выполняемые в игре. С помощью них вы сможете изменять и разнообразить геймплей.

1.1.2. Где они находятся?
В текстовых файлах с расширением bsl (BungieFrameWork Scripting Language), которые хранятся в директории ...\GameDataFolder\IGMD, где разложены по директориям с названиями уровней.

EnvWarehouse ? Тренировка и Склад Синдиката
manplant ? Завод Масаши
lab ? Лаборатория Ваго Биотек
Airport ? Нападение на аэропорт
Airport_III ? Грузовые ангары аэропорта
tctf ? Штаб-квартира TCTF
power ? Атмосферный комплекс (снаружи)
power_II ? Атмосферный комплекс (внутри)
state ? Региональное управление
roof ? Крыши
dream_lab ? Лаборатория доктора Хасегавы
neuro ? Закрытая лаборатория TCTF
tctf_ii ? Штаб-квартира TCTF (redux)
compound ? Горная резиденция Синдиката

Кроме того, существует директория global, обрабатываемая для абсолютно всех уровней. По умолчанию в IGMD она отсутствует, но при надобности её можно создать.

Оригинальные файлы скриптов обычно бывают трёх типов:
main (суффикс _main) ? файл, содержащий основную (вызываемую сразу при запуске уровня) функцию, main.
cutscene (суффикс _cutscene) ? содержит все катсцены (анимированные вставки) уровня.
logic (суффикс _level_logic или отсутствие суффикса) ? всё остальное (от музыки, создания персонажей и start до консолей да всевозможных триггеров).
Иногда встречаются и другие "тематические" скрипты - например, particle_scripts, или _spawn.

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

1.1.3. С помощью чего их можно редактировать?
Подойдет любой текстовый редактор, например, обычный виндовский Блокнот или WordPad. В идеале - любой удобный и привычный редактор с поддержкой C-подобного синтаксиса.
(!) Прежде чем редактировать bsl-файл, снимите у него в свойствах галочку "только для чтения".

1.1.4. Я испортил все скрипты, а оригиналы не сохранил. Что делать?
Переустановить игру ;) Или скачать этот бэкап.

1.2. Язык скриптов

1.2.1. Скриптовые команды
Примеры скриптовых команд в данном пособии будут приводиться следующим ("Shell-style") образом:
    название_команды [параметры]
Пример:
    chr_givepowerup [персонаж] [предмет] [количество]
На практике это должно писаться без квадратных скобок, например:
    chr_givepowerup Muro hypo 2

Существует более строгий (C-style) синтаксис:
    название_команды([параметры]);
Параметры перечисляются через запятую. Пример такого вида:
    chr_givepowerup(Muro, hypo, 2);
Таким образом, разделяя команды точкой с запятой, можно писать несколько команд в строчку. Кроме того, только в таком виде можно использовать в качестве параметра переменную.

Помимо вызовов функций, часто будут встречаться обычные присвоения переменным, то есть просто:
    название_переменной=[значение]

Во избежание недоразумений, обязательно учитывайте тип переменных - ошибки в этом плане ни к чему хорошему не приведут. Чаще всего проблемы возникают при обращении к персонажам: одним функциям нужны string-имена, другим - int-номера, а третьим подходят оба варианта. Следует понимать, что такое поведение чётко определено и, например, добиться чего-то от функции, требующей номера, зная только имя персонажа, нельзя.
В данном пособии пока что типы не указаны (разве что подразумеваются в виде имя/номер/персонаж, или [0/1]), но их всегда можно посмотреть в script_commands.txt (dump_docs), а также они будут указаны здесь в будущем. Когда-нибудь.

(!) Обязательно имейте ввиду, что все команды, функции, переменные и их значения чувствительны к регистру. "Konoko" нельзя менять на "konoko", "konoko" нельзя менять на "Konoko", "main" нельзя менять на "Main", "GrifElite02" нельзя менять на "grifelite02", "chr_set_health" нельзя менять на "chr_Set_Health", и так далее и тому подобное. Даже если очень хочется.

1.2.2. Функции

Традиционная структура всех функций такова:
func void [название] ([параметры])
{
    [команды]
}

При отсутствии параметров в скобках указывается void. Или ничего не указывается, даже сами скобки: в таком случае функция будет работать не хуже. Но лучше на всякий случай указывать void, иначе есть вероятность каких-нибудь глюков.
Если параметров несколько, то они отделяются запятыми; перед каждым параметром указывается его тип. Например:
func void function_name (int parameter_eins, float parameter_zwei, string parameter_drei)

(*) Все команды обязательно должны быть написаны внутри функций, иначе они не выполнятся или вовсе вызовут нефункциональность скрипта. Будьте внимательны с фигурными скобками, достаточно одной незакрытой, чтобы перестал работать весь скрипт.

В первую очередь в игре всегда обрабатывается главная функция, func void main (void). Попробуйте с помощью нее сделать простейший пример своего первого скрипта. Удалите все содержимое, скажем, папки Airport и создайте в ней файл bsl с любым названием. Напишите в нем:
func void main (void)
{
    chr_teleport 0 7010
    sleep 120
    win
}

Загрузите любую сохранку Аэропорта. Вы увидите, как Маи окажется на самолете в ремонтном ангаре, а через пару секунд уровень будет автоматически выигран. Т.е. вы написали подряд три команды, и они выполнились друг за другом. Теперь попробуйте разбить этот "сценарий" на несколько функций, которые вызываются одна из другой. Например:
func void main (void)
{
    start 120
}

func void start (int time_to_sleep)
{
    chr_teleport 0 7010
    sleep(time_to_sleep);
    win_level
}

func void win_level (void)
{
    win
}

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

1.2.3. Вилки
Кроме того, функции можно вызывать параллельно, без прерывания текущей функции. Для этого достаточно воспользоваться строчкой:
    fork [название функции]
Таким образом, создаётся вилка, и игра обрабатывает уже две (или больше, если вилок много) функции одновременно: начинает новую, и продолжает выполнять текущую.

Хотя эту возможность можно использовать каждый раз, когда нужно запустить какую-то функцию, не теряя хода нынешней, чаще всего вилки используются для того, чтобы запустить ожидание какого-либо события. Например:
func void wait_to_help(void)
{
    chr_wait_health Muro 200

    ai2_boss_battle = 0;
    muro_in_danger = 1;
    ai2_attack GrifElite01 char_0
    ai2_attack GrifElite02 char_0
    ai2_attack GrifElite03 char_0
    ai2_attack GrifElite04 char_0
    ai2_attack GrifElite05 char_0
    ai2_attack GrifElite06 char_0
}

Такая функция (это из последнего уровня, к финальной битве) позволяет по наступлении нетриггерного события (уменьшение здоровья Муро до 200) совершать какие-либо действия и вообще менять, в данном случае, стратегию боя.

Аналогично же можно, например, ждать выполнения какого-то приёма от игрока (да и от других персонажей ? тоже), и прописывать соответствующие действия в вилочной функции.

1.2.4. Переменные
В скриптах есть возможность создавать, редактировать и действовать относительно различных переменных. Их всего четыре вида: bool (двоичная), int (численная), float (с плавающей точкой, она же дробная, она же вещественная) и string (символьная). Двоичные переменные могут принимать всего два значения ? 0 или 1. Численные переменные ? целые (в основном используются натуральные) числа. С ними и можно выполнять всякие разные математические действия. Символьные же переменные могут принимать вид любой последовательности символов (как-то: слово), и могут использоваться для некоторых особых случаев, например, для dmsg. Также, тип string имеют имена персонажей (char_0, MutantMuro, и т.д.), названия предметов и оружий (w1_tap, hypo), и некоторые другие сущности. Никакие действия, кроме присвоения нового значения, к ним неприменимы. Присвоение переменной значения переменной другого типа пока что невозможно.

Для работы с переменной, в первую очередь её следует создать, с указанием типа. Это делается во внефункциональной области скрипта (то есть, пишется не в функциях, а за пределами фигурных скобок) следующей командой:
    var [тип] [название];
или
    var [тип] [название] = [значение];
(*) Каждое действие с переменными вне функций обязательно должно завершаться точкой с запятой (;). Иначе будут фатальные ошибки.

Где тип ? это bool, int, float или string, название ? то, как переменная будет обозначаться в скрипте, а значение ? это значение. =) Значение можно не указывать при создании, и тогда оно будет равняться нулю (для строковых переменных - пустой строке). Но лучше указывать всегда. В названии можно использовать почти любые символы, кроме функциональных (; , # " { } ( ) + - = ! < >). Например, некоторые буквы кириллицы (имеющие аналоги в английском языке, например, "о") работают и в названиях переменных, и в названиях функций, причём даже в английской версии игры. Но лучше не извращаться и обойтись английскими буквами, прочерком (_) и циферками. )

Например:
var string peremennaya = znachenie;
Изменять переменные можно обыкновенным присвоением, строчкой:
    [название переменной] = [новое значение];
Где значением может быть как константа, так и выражение. Например:
    peremennaya = peremennaya + 2;
Применяются переменные как напрямую, так и, чаще, в косвенном виде. Напрямую переменную можно использовать, во-первых, в командах dmsg и dprint (пока что только строковую переменную без каких бы то ни было излишеств), а во-вторых, для int-переменных, для установления численных параметров переменных: в chr_set_health, в количестве даваемых игроку предметов, в задержке, etc.

Косвенно переменные применяются if-конструкциях, для проверки: больше-меньше, равна-неравна переменная числу такому-то...
Например:
    if (hypo_counter ne 0) chr_givepowerup 0 hypo
    if (hypo_counter > 1) chr_givepowerup 0 hypo
    if (hypo_counter > 2) chr_givepowerup 0 hypo
    if (hypo_counter > 3) chr_givepowerup 0 hypo
    if (hypo_counter > 4)
    {
        dprint done
        chr_givepowerup 0 shield
    }
    if (hypo_counter eq 7) chr_givepowerup 0 invis


В такой системе игроку будут даваться гипо-спреи, до четырёх штук, в зависимости от переменной hypo_counter. Если счётчик равен пяти или более, то игроку даётся силовой щит. Если он равен ровно семи, даётся ещё и невидимость.
Также этот пример худо-бедно иллюстрирует работу if: выполнение следующей инструкции при истинности условия в скобках. условие - обычно сравнение двух значений (<, >, >=, <=, eq, ne), либо логическое выражение (and, or), в том числе отрицание (!).
Например, if (!hypo_counter) должно быть эквивалентно if (hypo_counter ne 0)

1.2.5. Строчки, начинающиеся с #
Итак, одна из важнейших составляющих скриптов... Это строчки, начинающиеся с волшебного символа "решётка" (#). Строки эти вообще не обрабатываются игрой. =) В них можно писать комментарии, закосяченные или "мягко" удалённые команды, анекдоты и свои мысли в адрес движка, который ни в какую не хочет нормально обработать, казалось бы, правильно написанный код: всё, что угодно. Движок этого читать, понимать и обрабатывать вообще не будет.
Единственное, что противопоказано в отношении этих строк (условно называемых комментариями) ? это писать символ # не в начале, а в каком-то другом месте строки, в которой написано что-то ещё (например, если хочется поставить свой комментарий не выше и не ниже, а сразу за комментируемой строкой). Сами эти строки (ту часть, что написана до #) движок обрабатывает без особых проблем, но последующую строку пропускает. Если строки завершать точкой с запятой (;), этой проблемы быть не должно, но лучше не морочиться.

1.2.6. Обозначение игрока
Для обозначения Маи лучше использовать индекс 0 (он везде прокатит), а не имя (например, char_0 или konoko - они работают не на всех уровнях). Более точно:
char_0 работает в уровнях: Тренировка, Склады Синдиката, Нападение на аэропорт, Штаб-квартира TCTF, Атмосферный комплекс (снаружи), Атмосферный комплекс (внутри), Крыши, Горная резиденция Синдиката.
konoko работает в уровнях: Завод Масаши, Лаборатория Ваго Биотек, Грузовые ангары аэропорта, Региональное управление, Лаборатория доктора Хасегавы.
На уровне Закрытая лаборатория TCTF игрок именуется Konoko (с заглавной буквы).
На уровне Штаб-квартира TCTF (redux) Маи обозначена как A_player. =)
Сам движок обычно показывает и обрабатывает словесные обозначения, да и в оригинальных скриптах они часто используются, но (особенно в глобальных скриптах, распространяющихся на все уровни) лучше всегда использовать 0.

2. Основы команд

2.1. Неклассифицируемые команды

2.1.1. Сообщения
Игра поддерживает два вида вывода сообщений (изначально предназначенных для отладки -_-) на экран:

    dmsg "[сообщение]"
либо
    dmsg [строковая переменная]
Выводит сообщение внизу экрана, посередине. С течением времени (зависит от активности движения игрока) сообщения плавно исчезают, одновременно может выводиться не более четырёх сообщений. Кроме того, сообщения можно раскрасить: для этого нужно часть сообщения представить в виде "[ц.текст]", где "ц" - буква, отвечающая за выбор цвета. Цветов всего восемь: b, c, g, l, o, r, u, y. Если указать иную букву, сообщение пропечатается вместе с квадратными скобками, буквой и точкой; если букву не указывать, цвет будет белым, также, как текст вне скобок.
Для наглядности приложено отображение команды
    dmsg "[b.B][c.C][g.G][l.L][o.O][r.R][u.U][y.Y][.W]"
http://onimia.ru/forum/attachment.php?item=1549&amp;download=1

    dprint [сообщение]
При включенном режиме разработчиков, отображает сообщение в консоли - снизу слева. Никакого оформления не предусмотрено, команда предназначена для отладки. Все кавычки в сообщении не печатаются. Команда очень часто встречается в оригинальных скриптах.

2.1.2. Кинематика
Появляющиеся по углам во время диалогов рожицы персонажей контролируются парой команд с весьма обширным количеством настроек:

    cinematic_start [название картинки] [ширина] [высота] [начальная позиция] [конечная позиция] [скорость] [отражённость]
Мгновенно создаёт в начальной позиции заданную картинку, которая сразу с заданной скоростью начинает движение к позиции конечной. Картинка может быть любой текстурой из данного или нулевого уровня - хоть мордашка, хоть вид неба, хоть текстура стенки или любого другого объекта. Ширину и высоту (в пикселях) лучше указывать те же, что и у самой текстуры, либо пропорционально меньше (растяжение обычно выглядит не очень красиво). "Стандартный" размер из оригинальных скриптов всегда 180х180. Скорость, кажется, указывается в пикселях во фрейм (1/60 секунды при соответствующем fps). Отражённость слева направо задаётся двоичным числом - или отражается, или нет. Несмотря на то, что в оригинальных скриптах всегда пишется текстовое true или false (или ничего не пишется, что соответствует false), вместо них прекрасно работают, соответственно, единичка и нулик. Текстовое представление здесь - такой же стереотип, как и написание команды по синтаксису со скобками и запятыми. Два равнозначных примера:
    cinematic_start (MUTANTMUROface, 180, 180, 19, 7, 20, false)
    cinematic_start MUTANTMUROface 180 180 19 7 20 0

    cinematic_stop [название картинки] [конечная позиция] [скорость]
С заданной скоростью ведёт уже созданную картинку к конечной позиции, по достижении которой картинка пропадает.

Начальные и конечные позиции - числа от 1 до 25, номера расположенных в строгом порядке позиций на экране и за ним. Их порядок также есть в прилагаемой иллюстрации, где белым прямоугольником обозначена видимая на экране область, а чёрным закрашено окружающее пространство. При указании позиции с номером более 25, кинематика работать не будет. Позиция с нулевым номером расположена в левом верхнем углу видимой области.
http://onimia.ru/forum/attachment.php?item=1550&amp;download=1

Более точно расположение кинематики можно определять следующими переменными:
    cinematic_xoffset=[число]
    cinematic_yoffset=[число]
Горизонтальный и вертикальный отступы от края (т.е. к каждому краю прилегают три видимые позиции; нижний край кинематики расположен чуть выше "настоящего") соответственно. По умолчанию горизонтальный отступ равен 20, вертикальный - 65.

2.1.3. Границы видимости

    gs_farclipplane_set [расстояние]
Выставляет расстояние абсолютной обрезки. Выглядит как плоскость, перпендикулярная линии взгляда (aiming vector), за которой ничего нет. Обычно это не очень красиво (хоть и экономит ресурсы), поэтому в большинстве случаев стоит либо выставить очень большое расстояние, либо использовать его совместно с плавностью тумана.

    gl_fog_start=[число]
    gl_fog_end=[число]
Данные переменные определяют густоту тумана, выражаются числами на отрезке [0,1]. обычно end равен единичке (то бишь, абсолютный туман на расстоянии farclipplane), а start - что-нибудь вида 0.9**. Стоит взглянуть на практике, чтобы оценить масштабы: даже 0.99 - отнюдь не идеальная видимость. чем больше start в данном случае, тем менее густой будет туман. Если выставить end меньше, чем start, то лучшем случае получится затуманивание в другую сторону - плохая видимость модели самого игрока.
Также стоит учитывать, что некоторые части некоторых тел (например, в случае Маи это голова: видимо, это касается "блестящих" поверхностей и частиц) не затуманиваются, и при слишком большом затуманивании будут очень некрасиво смотреться. Кроме того, жестокий туман сейчас менее актуален, так как современные машины довольно свободно отрисовывают весь уровень при отсутствии тумана и пятимиллионном farclipplane... Но это уже зависит от вкуса и ситуации. И вообще атмосферы.

    gl_fog_start_changeto [число] [время]
    gl_fog_end_changeto [число] [время]
Плавно меняют вышеуказанные величины в течение заданного времени.

    gl_fog_red=[число]
    gl_fog_green=[число]
    gl_fog_blue=[число]
Определяют цвет тумана по трём составляющим. Числа из отрезка [0,1]. Чем туман более густ, тем больше в нём проявляется данный цвет (опять же, масштабы могут быть довольно неожиданны, стоит подбирать на практике).

Помимо тумана, есть любимая почти всеми квакерами и не только функция угла обзора:
    gs_fov_set [угол]
Не так мило с учётом вида от третьего лица, но всё же... Для некоторых размазанные края слишком привычны, чтобы испытывать дискомфорт. Кроме того, малые углы можно использовать как зум... В специфичных случаях.

2.1.4. Спецэффекты

    splash_screen [текстура]
Показывает заданный сплэш-скрин. Как обычно, при начале и конце уровня. Не забываем, что это не хухры-мухры, а большие TXMB. Можно, например, фон меню показать. ) Но, в отличие от кинематики, не какую попало текстуру.

    fade_out [red] [green] [blue] [время]
В течение заданного времени "затемняет" весь экран до указанного цвета: red - красная составляющая, green - зелёная, blue - синяя, все на отрезке [0,1]. Кинематика рисуется поверх фейдинга, сообщений при нём нет вообще.

    fade_in [время]
В течение заданного времени возвращает видимость из фейдинга. Причём если fade_in вызван, пока экран окончательно за затемнился от fade_out, то экран мгновенно зальёт итоговым цветом, и уже из этого положения начнёт просветляться.

    ui_show_element [элемент] [0/1]
При нуле прячет указанный элемент (left с оружием, компасом и боеприпасами или right со всем остальным) интерфейса.

    ui_fill_element [элемент] [0/1]
Заполняет указанный элемент интерфейса. То бишь, показывает все шесть обойм/гипо, заполняет показатель здоровья (вплоть до даодановой области: однако, цвет будет соответствовать реальному количеству), все стороны повреждений, всю окружность компаса, стрелочку, и т.д.
Все доступные варианты: health, damage, invis, shield, hypo, weapon, ammo, compass, arrow, ballistic, energy, lsi.

    ui_flash_element [элемент] [0/1]
При единице указанный элемент интерфейса начинает мигать.

    ui_show_help [0/1]
Показывает подсказки к интерфейсу. =)

    ui_suppress_prompt=[число]
При единице отключает всплывающие подсказки (о новых заданиях, сохранениях, и т.п.)

    letterbox [0/1]
Включает катсценообразные чёрные полоски (но не катсцену!). Когда они есть, не отображаются сообщения (типа dmsg) и элементы интерфейса.

    begin_cutscene
Включает катсцену. Катсцена подразумевает сразу ряд функций (ai2_allpassive 1, cm_detach, letterbox 1, ai2_allpassive 1, input 0 и т.п.), и в оригинале не позволяет выйти в меню, например.
Считается функцией без аргументов, однако при указании параметра weapon игрок ещё и прячет оружие.

    end_cutscene
Завершает катсцену.

2.1.5. Конец
За выигрывание уровня отвечает команда:
    win

За проигрыш:
    lose

Обычно в ресурсах к смерти игрока привязана обыкновенная скриптовая функция "you_lose", которую, наверное, можно было бы даже сделать глобальной. Туда пишется фиксация камера в одном месте (cm_detach), затемнение экрана (fade_out), и уже потом, спустя несколько секунд - собственно lose. Разумеется, всё это можно менять каким угодно образом.

2.2. Читы

Чтобы включить некоторые из читов (применительно к игроку), можно воспользоваться строкой:
    [название чита]=[0/1]
Где единица означает включение, нуль ? отключение. Пример:
    invincible=1
Названия читов отличаются от тех, что пишутся в F1:
invincible ? неуязвимость (liveforever)
unstoppable ? неостановимость (canttouchthis)
omnipotent ? смертельный удар (touchofdeath)
chr_big_head ? большая голова (bighead)
chr_mini_me ? мини-режим (minime, он же behemoth)

Кроме того, для режимов mini_me и big_head имеются специальные переменные для их регулирования:
    chr_big_head_amount=[множитель к размерам головы]
Множитель размеров головы по умолчанию равен 4. Нормальный размер ? 1.
Также есть и множитель к mini_me: при его увеличении игрок становится больше (как при behemoth), при уменьшении ? меньше (minime). Стандартное значение для чита minime равно 0.5. Нормальный размер, разумеется, 1:
    chr_mini_me_amount=[множитель размера игрока]
Кроме того, читы можно применять и на конкретных персонажей (как на игрока, так и на АИ). Для этого применяется строка такого вида:
    chr_[название чита] [персонаж] [0/1]
Пример:
    chr_unstoppable Muro 1
Названия читов:
invincible ? неуязвимость (liveforever)
unstoppable ? неостановимость (canttouchthis)
super ? свечение Даодана (chenille*)
ultra_mode ? ультра режим (killmequick)
boss_shield ? щит боссов (bigbadboss, chenille*)
*чит chenille включает в себя и chr_super, и chr_boss_shield

Чит slow motion (carousel) работает вообще по-другому, и пишется так:
    slowmo [время действия]
Время считается во фреймах. Например, для десяти секунд ("обычных" секунд):
    slowmo 600
Включить этот чит на бесконечное количество времени невозможно. Можно только поставить очень-очень большое время. =) например, 5000000 ? это почти сутки "нормального" времени.

2.3. Предметы и оружие

Предметы даются строчкой:
    chr_givepowerup [имя персонажа] [предмет] [количество]
или
    give_powerup [предмет] [количество] [номер персонажа]
Например:
    chr_givepowerup OutroNinja invis -1

Оружие:
    chr_giveweapon [имя персонажа] [оружие]
или
    chr_weapon [номер персонажа] [оружие]
Пример:
    chr_giveweapon MutantMuro w11_ba1

Обязательно различайте функции, требующие имена и функции, требующие номер. Если в give_powerup не указать номер персонажа, предметы будут выданы игроку.
Оружие в каждом случае можно указывать по названию (см. ONWC), либо по номеру. Но из-за неочевидной нумерации лучше обойтись названиями.
В обоих случаях с предметами, количество можно не писать: тогда оно будет принято за единицу. "Количество" фазовой маски измеряется во времени действия: по стандарту оно равно 1800 (во фреймах 30 секунд). "Количество" полного силового щита равно 100, что и является стандартом при выдаче. Если ставить для этих предметов бОльшие числа, то они будут правильно обрабатываться, однако в правом ui-элементе (где указываются гипо, щит, фазовая маска, здоровье...) будут возникать графические глюки. =) Можно указывать и отрицательные значения, тогда предметы будут "отбираться". Если и само количество предметов окажется ниже нуля, то оно будет считаться по модулю 65536. Например, (-1 mod 65536) = 65535. Но если у персонажа Наличие специального предмета (lsi) определяется булевой переменной и выдаётся единожды в количестве одной штуки.

Можно создавать предмет/оружие прямо "на земле", для предметов это строчка:
    powerup_spawn [предмет] [место]
Для оружия:
    weapon_spawn [оружие] [место]
Заспавненное таким образом оружие, если его подобрать и затем бросить, исчезает как после чита munitionfrenzy (оружие, которое не трогали, будет лежать там сколько угодно), что можно изменить строчкой:
    wp_disable_fade=[0/1]
При нуле всё останется, как было, а при единице оружие не будет исчезать. Вообще. Другой вариант ? можно повысить значение следующей переменной, она отвечает за время, по прошествии которого оружие и будет исчезать. Время указывается во фреймах. По стандарту значение этой переменной равно 360 (6 секунд):
    wp_fadetime=[время]
Названия предметов:
hypo ? гипо-спрей
ammo ? баллистическая (красная) обойма
cell ? батарейка (зелёная обойма)
shield ? силовой щит
invis ? фазовая маска
lsi - специальный предмет (блокнот, ключи и т.п.)

При количестве гипо/обойм больше шести, они не отображаются на индикаторах, но существуют "в уме". Максимальное значение для всех предметов, кроме специального, составляет 65535.

Названия оружий:
w1_tap ? пистолет Кемпбелла Mk4
w2_sap ? пистолет-пулемёт Чёрная Гадюка
w3_phr ? плазменная винтовка
w4_psm ? фазовый потоковый излучатель
w5_sbg ? шаромёт
w6_vdg ? электрошок
w7_scc ? ракетница
w8_mbo ? ртутный арбалет
w9_scr ? пушка-Крикун
w10_sni ? оружие Мукада
w11_ba1 ? пушка Барабаса
w12_ba2 ? точка-фигушка, не стреляет

Нижеследующая команда заставляет персонажа спрятать/вынуть оружие:
    chr_forceholster [персонаж] [0/1]
Где при нуле оружие вынуто, при единице ? спрятано.

Для очищения инвентаря используется команда:
    chr_inv_reset [персонаж]

2.4. Двери

Номера дверей выражаются натуральными числами, которые можно найти в оригинальных скриптах. Обычно двери в каждом уровне пронумерованы "послойно", реже ? по порядку прохождения/открытия.

Собственно, команды:
    door_open [номер двери]
и
    door_close [номер двери]
Первая строчка открывает дверь, вторая ? закрывает.
Не путать с:
    door_unlock [номер двери]
и
    door_lock [номер двери]
Где на дверь видимого воздействия нет. Первая строка позволяет как игроку, так и AI, открывать "закрытую" дверь (по приближению/кнопке "действие"), вторая ? запрещает. В игре большинство этих команд (в оригинальных скриптах ? практически всех) сопровождается зелёным-красным огоньком.
Управлять этими зелёными/красными лампочками у дверей можно и нужно независимо от дверей: можно открыть/закрыть дверь, не меняя цвета индикатора, или менять цвет, не изменяя состояния двери. А можно даже честно показывать индикатором состояние двери. Так или иначе, команда:
    particle [название индикатора] do [start/stop]
Где start ? зелёный цвет, stop ? красный.
Названия партиклей тоже ищутся вручную по оригинальным скриптам. Выглядят названия примерно так: lock[номер двери]_locklight01 (последние две цифры меняются, если есть несколько индикаторов к одной двери).

И, наконец,
    door_jam [номер двери]
и
    door_unjam [номер двери]
Первая команда ? фиксация двери. Если дверь была открытой к наступлению команды ? она и останется открытой. Аналогично с закрытой. Дверь может фиксироваться даже тогда, когда она наполовину закрыта (специально для оптимистов ? наполовину открыта ^_^). В этом случае пройти её можно лишь с помощью кувырка/подката.
Вторая, соответственно, снимает эффект этой команды.

Пример:
    door_unlock 12
    door_open 12
    sleep 120
    door_close 12
    door_lock 12
    sleep 15
    door_jam 12


Список дверей по уровням с номерами, названиями, скриншотами, изначальными положениями и названиями сопутствующих индикаторов можно взять на OniStuff.

2.5. Консоли

Когда в игре нажимается какая-либо консоль, в скрипте запускается определённая функция, везде выглядящая по-разному. Например: console200, level_4a, console_truckinfo, grifftext. К некоторым консолям, впрочем, привязано сразу несколько функций.
По нажатии на консоль она запускает функцию единожды: далее изображение на консоли превращается в иллюстрацию "белого шума".
В функции, помимо предназначенных для дебага команд dprint (и, в некоторых консолях, проверок на нажатие других консолей, etc.), встречаются следующие строчки:
    text_console [название текста]
Открывает окошко информационных консолей (выводит текст). Название текста можно искать по скрипту, либо непосредственно в ресурсах.
Название текста обычно выглядит так:
    level_[номер уровня][буква, выражающая номер, чаще всего можно видеть "a"]
Например: level_4a, level_11a, level_19e.

Эта команда (как и остальные консольные команды далее) работает не только в функции консоли, но и в любом месте скрипта ? достаточно прописать эту строчку, и (в случае с этой командой) окно с информацией появится. В любое время.
    console_reset [номер консоли]
Перезагружает консоль ? изображение ненастроенного телевизора исчезает, консолью снова можно воспользоваться. Те консоли, которые работают постоянно (информационные), всего лишь имеют в конце своей функции такую строчку.
В данной команде нужен номер консоли (число, ищется по скриптам вручную. не путать с названием консоли). Ищется он обычно легко ? достаточно посмотреть на число, стоящее после одного из оригинальных console_reset'ов. Так как в оригинальных скриптах эта команда обычно стоит в конце консольных функций, к которым она относится, это и есть искомый номер.
    console_deactivate [номер консоли]
Деактивирует консоль.
    console_activate [номер консоли]
Активирует консоль обратно.

Кроме того, в функцию консоли можно написать любые команды. ^_^
Список консолей во всех уровнях с номерами, скриншотами и вызываемыми функциями можно взять на OniStuff.

2.6. Камера

    cm_reset
Ставит камеру в надлежащее ей место за игроком и снимает все другие команды (типа интерполейта или детача). Чем чаще будет прописана эта команда (или хотя бы чем меньше будет прочих cm_ команд), тем удобней играющему.

    cm_detach
Фиксирует камеру там, где она находилась на момент запуска команды. В оригинальных скриптах обычно использовалась при смертельном падении и самой смерти (без этой команды можно было бы крутить камеру вокруг трупа или наблюдать падение во всех деталях).

    cm_distance=[число]
Задаёт дистанцию от камеры до игрока. В единицах длины. По стандарту равняется 33. Если поставить много (в районе пятисот или даже тысячи), то можно будет осматривать сразу почти весь уровень. Если выставить gl_fog_start=1 и большой gs_farclipplane_set, конечно.

    cm_height=[число]
Задаёт высоту точки, на которую ориентирована камера. По стандарту равняется 15 (уровень головы Маи). Уровень ног/пола ? 0.

    cm_canter_unarmed=[число]
    cm_canter_weapon=[число]
Задают высоту камеры относительно фокусной точки (в безоружном и вооружённом состоянии соответственно). По умолчанию без оружия 8 (камера чуть выше), с оружием 7 (обзор ближе к горизонтальному).
В случае, если камера не фиксирована относительно игрока (например, командой cm_orbit), и игрок сам может крутить головой в вертикальной плоскости, просто определяет угол наклона камеры относительно собственного горизонтального "взгляда" персонажа.

    cm_jello [0/1]
Включает/выключает режим камеры jello?. Суть режима в том, что все препятствия между камерой и наблюдаемым объектом (обычно игрок) становятся полупрозрачными. По стандарту этот режим включен, но его можно и выключить ? тогда стены будут успешно скрывать от камеры всё разворачивающееся за ними действие.

    cm_jello_amt=[число]
Задаёт уровень видимости "просвечиваемых" через jello?-режим объектов, в процентах. По стандарту равняется 20, чем больше, тем виднее мешающийся объект. 0 ? совсем не видно, зато улучшается видимость игрока.

    cm_jello_radius=[число]
Этой переменной задаётся расстояние от наблюдаемого объекта, на котором в действие вступает режим jello?. По стандарту равняется 12 (разумеется, меньше, чем cm_distance).

    cm_wait
Заставляет движок задерживаться перед дальнейшим выполнением команд, пока не закончится текущая манипуляция с камерой.

    cm_orbit [скорость] [угол]
    cm_orbit_block [скорость] [угол]
Вертит камеру вокруг имеющейся точки (обычно ? игрок) с заданной скоростью до заданного угла. скорость задаётся числом от -360 до 360, но уже после |10| верчение камеры может отрицательно сказаться на желудке. Отрицательное число вертит камеру по часовой стрелке, положительное ? против.
Угол можно не указывать (или указать -1, что является эквивалентом бесконечности), и тогда камера будет вертеться бесконечно. Если же задать его, то камера опишет с заданной скоростью лишь часть окружности, заданную этим углом. измеряется он в градусах (360 полная окружность, 180 полуокружность, 90 прямой угол, и т.п.) и отсчитывается против часовой стрелки. При указании угла больше 360 градусов, угол всё равно равен именно 360 градусам.
Команда с суффиксом _block заставит движок ожидать конца поворота, перед тем как дальше выполнять скрипт.
Важный момент: команда жёстко фиксирует вышеописанное положение камеры, в частности, не позволяя игроку самостоятельно шевелить взглядом по вертикали. Пока не наступит cm_reset.

    cm_interpolate [камера] [время]
    cm_interpolate_block [камера] [время]
За заданное время (во фреймах, обычно 60=1сек) камера перемещается в некоторую конкретно заданную статичную позицию. Позиции все заданы разработчиками и названы словесными обозначениями (например, OutroCamDisk, BomberCam00, и т.п.). Если задать достаточно большое время, то переход к этой камере будет оч.плавным. Если задать маленькое, вплоть до 0 ? порезче.
Обычно эта команда используется лишь в катсценах, хотя можно найти ей и некоторые другие применения...
Команда с суффиксом _block заставит движок ожидать конца поворота, перед тем как дальше выполнять скрипт.

    cm_anim both [фильм]
    cm_anim_block both [фильм]
Эта команда вызывает что-то вроде динамичного интерполейта. Или последовательности интерполейтов, идущих в одной совокупности. Используется обычно для красоты катсцен. За что отвечает _block, полагаю, понятно. )

2.7. Звуки

Вообще, со всеми вызываемыми звуками есть очень строгое распределение по типам (ambient, impulse, и т.п.), смотреть в OSBD.

Музыка расписана здесь. =)

    sound_music_start [музыка] [громкость]
Запускает заданную музыку с заданной громкостью. Музыка обычно обозначается тем же названием, что и системное, причём без циферков, обозначающих сэмплы. Например: mus_asianb, mus_main03_hd, atm_gr09.
Громкость обозначается числом от 0 до 1. например, 0.6.

    sound_music_volume [музыка] [громкость] [время]
Изменяет громкость играемой музыки до заданной в этой команде в течение заданного же (в секундах) времени. Если время указано и достаточно велико, то изменение будет плавным. Если равно нулю или вовсе не указано ? мгновенным.

    sound_music_stop [музыка]
Останавливает играемую музыку. За счёт деления музыки на несколько участков, остановка ведётся плавно (по завершении играемого сэмпла начинает играть сэмпл эндинга, а затем и останавливается).

    sound_dialog_play [диалог]
Проигрывает один диалоговый звук (одну реплику).

    sound_dialog_play_interrupt [звук]
Прерывает текущий звук диалога (если таковой имеется), и запускает новый также, как и обыкновенный sound_dialog_play.

    sound_dialog_play_block pause
Проигрывает несуществующие звук pause, задерживая течение скрипта вплоть до окончания проигрывания стоящей перед этой командой sound_dialog_play. Позволяет расписывать диалоги, непосредственно рассчитывая задержки относительно окончаний реплик.

    sound_impulse_play [импульс]
Проигрывает звук класса импульсов (короткие звуки, например, c04_14_02konoko).

    sound_ambient_start [амбиент] [громкость]
Проигрывает звук класса эмбиентов. Они бывают как зацикленные, так и нет. и вообще разными бывают. Но команда от этого всё равно не меняется, так что неважно... Громкость задаётся также, как и в музыке ? дробным числом от 0 до 1.

    sound_ambient_volume [амбиент] [громкость] [время]
Меняет громкость проигрываемого эмбиента за заданный промежуток времени. Плавно.

    sound_ambient_stop [амбиент]
Форсирует остановку играемого эмбиента. Обычно они, как и музыка, расписаны по сэмплам, поэтому остановка будет такой же плавной и красивой.

Также к звукам можно отнести следующую садистскую штуку:
    chr_pain [персонаж] [уровень]
Заставляет персонажа кричать от боли заданного уровня (light, medium, heavy, death).

2.8. Таймеры

Таймеры задаются и действуют предельно просто.
    timer_start [время] [функция]
Время указывается в секундах (не во фреймах!). И, собственно, через этот промежуток времени запускается заданная функция.

Используются таймеры не для обычного аналога вилочного слипа с указанием времени в правом нижнем углу экрана, а для отключаемого (по какому-либо событию) вызова функции (чаще всего ведущей к lose).

Останавливается таймер не менее простой командой:
    timer_stop
По её вызову, таймер мгновенно останавливается и отключается, не вызывая той функции.

В любой момент времени в игре может быть лишь один таймер, не больше.

Мih@ » 22-07-2008 09:04:50

3. Персонажи

3.1. Основные команды

Каждый персонаж в игре имеет свой индекс (номер), имя и стартовое расположение. Персонажей из одного уровня нельзя переместить в другой уровень или подредактировать его вид, приёмы, реплики - во всяком случае, лишь скриптами, без редактирования ресурсов игры, что стало возможным лишь с относительно недавнего времени. По крайней мере, перенос и глобализация. =) Ныне есть АЕ, и можно об этой проблеме забыть.
Когда персонаж создаётся, он находится именно на своей стартовой позиции, которая, опять же, прописана не в скриптах, а в файле уровня (Character.BINA).
В данной главе должна довольно чётко обозначаться граница между индексом и именем персонажа. Для некоторых операций индекс более приемлем, но он зависит от порядка спавна, и, например, при нелинейном прохождении скрипта с созданием персонажей по ходу выполнения, он может оказаться разным. Едва персонаж появился, номер фиксируется за ним до самой смерти и даже на некоторое время после неё, после чего может быть занят персонажем, созданным уже после его исчезновения.
Индекс игрока (Маи) - всегда нулик (0), имя же варьируется от уровня к уровню, см. пункт 1.2.6. Имя лучше особо не использовать, а для глобальных функций это вообще противопоказано. Разве что использовать их вызов, предварительно кидая из функции конкретного уровня переменную, определяющую уровень и/или имя. Либо определить единое имя в ресурсах игры. -_- Либо пользоваться chr_name, когда оно появится.
Также у многих персонажей в ресурсах прописано название функции, которая будет вызываться при смерти этого персонажа. Иногда к ним добавляются функции, вызываемые вступлением в диалог с персонажем, нанесением ему первого урона, и т.п.
Список персонажей по уровням с указанием имени, внешнего вида, класса, команды, оружия и прочих предметов, а также всех привязанных функций можно взять на OniStuff.

3.1.1. Создание

    ai2_spawn [имя персонажа] [force]
Собственно создаёт персонажа на его стандартной стартовой позиции и со стандартными параметрами (команда, здоровье, оружие).
force позволяет спавнить одного и того же персонажа более одного раза, после чего, впрочем, могут возникнуть проблемы с дальнейшим управлением этими персонажами. Используйте с осторожностью - порой лучше обойтись командой chr_set_class, если необходимо создать иллюзию большого количестве одинаковых персонажей; и в любом случае старайтесь избегать слишком больших толп врагов, делайте упор на качество, а не количество. Больше 16 противников за раз, имхо, никогда не бывает нужно в принципе, иначе это уже моветон. Да видел, видел я свои скрипты, и rh3 тоже видел, вот потому и предостерегаю...
Также есть команда, позволяющая создать сразу всех персонажей, какие только есть на данном уровне. Кстати, ещё имейте ввиду, что на некоторых видеокартах (особенно от NVidia -_-) могут возникать критические ошибки из-за наличия слишком большого количества активных персонажей (таковыми становятся персы, находящиеся примерно в поле зрения игрока). Проблема pathfinding сетки была исправлено в последних версиях daodan'а, да и нижняя планка нвидии лежала на 32 противниках, чего уже предостаточно.

    ai2_spawnall
Страшная штука. Спавнит всех. Всех, кто перечислен в Character.BINA.

    chr_create [индекс персонажа] [start]
Создаёт тело. Тело имеет все "физические" свойства нормального персонажа, но обделено мозгом - АИ в нём отсутствует. Тела обычно используются только для различных полу катсценовых эффектов (start как раз отсылает тело на дело, для которого оно предназначено). Например, в "Региональном управлении" АИ не имеют Мукад в самом начале уровня, Мукад, тыкающий терминал во время катсцены и Мукад с ещё одним ниндзей, удирающие в самом конце. Подобных тел можно создавать сколь угодно много, пока не будут достигнуты лимиты прорисовывания и памяти. И важно не путать индексы этих тел с номерами персонажей (которые присваиваются по порядку спавна).

3.1.2. Первичная настройка

    chr_set_health [имя персонажа] [количество здоровья]
    chr_health [номер персонажа] [количество здоровья]
Даёт заданному персонажу заданное количество здоровья. Здоровье прибавляется и отнимается плавно, как при использовании гипо-спрея и при ударе, особенно сильном. Полное здоровье Маи без эффекта Даодана равно 200 единицам на среднем и сложном уровнях, и 260 на простом. Если быть точным, по умолчанию на простом уровне у игрока установлено 130% от "обычного" здоровья (а на сложном - 125% у врагов).
В принципе, количество здоровья не ограничивается никакими разумными рамками, но всё здоровье, превышающее верхнюю границу даоданавой силы, отображается как равное верхней границе, и соответствует аналогичной даодановой силе. С течением времени избыток здоровья уменьшается - с той же скоростью, что и обычный даодановый излишек.

    chr_full_health [имя персонажа]
Задаёт персонажу максимум здоровья. Команда не изменяет численное количество здоровья, которое является максимум для данного персонажа, а просто даёт ему ровно столько здоровья, сколько можно до вызова эффекта Даодана. И отображает в консоли его численное количество. Причём здесь плавность отключена: здоровье выставляется мгновенно.

    chr_changeteam [имя персонажа] [название команды]
Задаёт принадлежность персонажа к какой-либо команде. Принадлежность к командам влияет как на поведение персонажа (ИИ, за исключениям мирного люда, дерётся с "чужими", не трогает "своих" в соответствии с командными принадлежностями, а также по-разному ведёт себя с "нейтральными" персонажами), так и на сами боевые контакты ("своих" невозможно ударить).
Названия команд и их взаимоотношения строго (с точки зрения скриптов) прописаны в ресурсах, и делятся на TCTF, Syndicate, Konoko, Neutral, Switzerland (катсценовые персонажи), SyndicateAccessory (девушко в начале второго уровня и синдикатские нейтралы последнего уровня), RogueKonoko (в Лаборатории Хасегавы, порой и сама Маи), SecurityGuard (Региональное управление). Будьте внимательны: названия команд, как и всё остальное, чувствительны к регистру, написания вроде "neutral" или "Tctf" работать не будут.
Менять команду можно и самому игроку.

    chr_teleport [имя персонажа] [номер точки]
Мгновенно переносит персонажа к заданному флагу на уровне.

    chr_location [номер персонажа] [абсцисса] [ордината] [аппликата]
Мгновенно переносит персонажа в заданную координатами точку на уровне. Более точная штука, чем телепорт, но требует именно номера, а не имени.
Если Вы не имеете примерного представления о том, куда направленны оси абсцисс и аппликат (ордината всегда направлена вверх) и где находится точка отсчёта - это очень просто определить в консоли:
    where
Напишет в консоли, где Вы находитесь в данный момент, а
    chr_location 0 0 0 0
или
    goto 0 0 0
Мгновенно перенесёт в точку отсчёта. Всё дальнейшее легко расчитать и проверить опытным путём, либо можно попросту бегать (иногда с использованием примерного chr_location для экономии времени, либо с использованием обильного количества девмодовских возможностей по перемещению) по уровню между всеми нужными точками, запрашивая для них where.
Кстати, chr_location без аргументов тоже показывает текущее местоположение игрока, а при перемещении - и старую, и новую координату. Просто where более предназначена для этого, и угол поворота персонажа заодно показывает - мелочь, а приятно. )
Есть и функция, прорисовывающая отрезок, соединяющий игрока с заданной точкой:
    chr_draw_dot [абсцисса] [ордината] [аппликата]

    chr_facetoflag [персонаж] [флаг]
Поворачивает данного персонажа в направлении, на которое ориентирован данный флаг (не "поворачивает к флагу"). Возможно использование, например, сразу после телепортации, чтобы персонаж не смотрел куда попало. Перед использованием стоитт ознакомиться с направлением facing vector'а данного флага, чтобы направление не оказалось неожиданным. =)

    chr_set_class [номер персонажа] [класс]
Задаёт персонажу класс - ONCC в ресурсах, содержащий все физические данные и ссылки на них, включая модель, текстуры, набор анимаций, звуки и т.п. Имя, номер, независимые от класса свойства АИ и всё прочее остаётся прежним.

    chr_nocollision [персонаж] [0/1]
Читообразная функция, отключающая коллизии с архитектурой. Позволяет ходить сквозь стены и прочие предметы, а также ходить по воздуху. Впрочем, комфорта в этом не так уж и много: персонаж без коллизий фиксируется на своём горизонтальном уровне и не может перемещаться по вертикали. Только прыгнуть, но после этого он "зависнет" на новой горизонтальной плоскости в полёте, пока не превысит лимит "падения" и не погибнет. Коллизии с персонажами и подверженность ударам (в отличие от оружия) при этом остаётся.

    chr_enable_collision=[0/1]
Что-то вроде противоположности вышеуказанной функции. Это не функция, а переменная, отключает коллизии не при единице, а при нуле, отключает не одному персонажу, а всем сразу, и  коллизии в данном случае имеются ввиду между персонажами, можно бить и пробегать насквозь (только броски работают из-за иной механики). С архитектурой и оружием коллизии остаются.

    chr_unkillable [персонаж] [0/1]
Делает персонажа неубиваемым. Отличается от invincible тем, что здоровье отнимается без проблем, при достижении нуля возникают соответствующие смерти эффекты (вспышка, звуки, падение), но смерть совсем не фиксируется и персонаж спокойно может встать и отомстить.

    chr_weapon_immune [персонаж]
Делает персонажа неуязвимым к оружию. Необратимо.

3.1.3. Удаление

    ai2_kill [имя персонажа]
Убивает персонажа - так, как если бы он умер обыкновенной насильственной смертью - с анимацией и звуками смерти, выпадением имущества, наличием трупика и вызовом соответствующей функции.
Убитые таким (как и традиционным) способом персонажи не удаляются полностью (вернее, преодолевают стандартное разложение - постепенное удаление различных свойств, физического присутствия, и т.д.), и впоследствии их можно накачать здоровьем, поднять на ноги и анимировать всяческой скриптовой некромантией, но полноценно оживить его вряд ли получится: как АИ, так и боевые настройки после смерти улетают на небеса. >_< Проще создать персонажа заново, предварительно удалив прошлого следующей командой:

    chr_delete [персонаж]
Удаляет персонажа. Безо всяких эффектов, следов и вызова функции смерти (впрочем, chr_wait_health при удалении срабатывает). Может удалить и мёртвое тело. После удаления персонажа можно создать заново - через ai2_spawn или хотя бы chr_create.

Есть и оружие массового поражения:
    chr_kill_all_ai
Убивает всё живое, что уже заспавнилось.

Также стоит упомянуть о блокировании полного удаления:
    chr_death_lock [персонаж] [0/1]
При включенном блоке, персонаж не будет после смерти проходить все стадии разложения (вплоть до удаления), а оставит бесполезное тело со всеми вытекающими. Например, при этом не освободится его порядковый номер, что позволит более точно контролировать эту самую нумерацию.

3.2. ИИ

Для того, чтобы персонажи оправдывали расшифровку "искусственный интеллект" и не были "искусственными идиотами", существует довольно широкие возможности по контролю их поведения. Без скриптового контроля, персонаж умеет только участвовать в драке, завидев противника, либо выполнять данную ему заранее работу.

    ai2_passive [персонаж] [0/1]
При единице делает персонажа пассивным. В таком состоянии персонаж не принимает участия в драке, не встаёт, если его уронили (исключение - автоматическое поднятие, если персонаж был за областью видимости временно не обсчитывался), и не выполняет некоторые задачи - патрулирование, включение консоли тревоги, и т.п. Традиционно более распространена команда, управляющая пассивностью сразу всех персонажей:
    ai2_allpassive [0/1]
По сути, обезвреживает и останавливает всех, что незаменимо для дебага и сценок.

    ai2_active [персонаж]
Делает персонажа активным. То бишь, прорисовываемым, анимируемым, обсчитываемым движком. Обычно активность/неактивность автоматически переключается при наличии/отсутствии данного персонажа вблизи поля зрения. Обратная команда:
    ai2_inactive [персонаж]

Для фиксации персонажа в активном состоянии, чтобы он не переключился автоматически:
    chr_lock_active [персонаж]
Для расфиксации, соответственно:
    chr_unlock_active [персонаж]

    ai2_attack [персонаж_1] [персонаж_2]
Заставляет персонажа_1 атаковать персонажа_2, по возможности игнорируя всё остальное. можно таким образом заставить персонажа атаковать того, кто с ним в одной команде, но при отсутствии оружия цели достигнут лишь броски (которые у АИ работают не совсем как у людей). Не работает при пассивности агрессора.

    ai2_movetoflag [персонаж] [номер точки]
Посылает персонажа идти к заданному флагу.

    ai2_comehere [персонаж]
    ai2_followme [персонаж]
Посылают персонажа идти к точке, где стоял игрок на момент вызова этой функции. ai2_followme должна была бы регулярно уточнять текущее расположение игрока, но не делает этого из-за небольшой скосяченности. Для не самых замороченных случаев можно воспользоваться аналогом типа:
var bool follow;
func followme(string ai_name, int step)
{
    ai2_comehere(ai_name);
    sleep(step);
    if(follow) fork followme(ai_name,step);
}

Где follow=1; followme [персонаж] [период обновления координат] позволяет включить следование, а follow=0; - выключить.

При задании движения важно уточнить, как именно персонажу следует двигаться - шагом, бегом, красться, вприпрыжку или боком/задом. Для этого используется следующая команда:
    ai2_setmovementmode [персонаж] [тип движения]
Где тип движения может быть creep, walk, walk_noaim, run, run_noaim.

    ai2_lookatchar [персонаж_1] [персонаж_2]
Заставляет персонажа_1 повернуться в сторону персонажа_2. Есть её более короткий аналог, поворачивающий персонажа к игроку:
    ai2_lookatme [персонаж]

Команды ai2_lookatchar, ai2_movetoflag и ai2_setmovementmode можно применить и к самому игроку, но при одном условии - передаче контроля ИИ следующей командой:
    ai2_takecontrol [0/1]
Где 1 включает эту возможность.

    ai2_makedeaf [персонаж] [0/1]
    ai2_makeblind [персонаж] [0/1]
Глушит и слепит персонажа соответственно. глухой персонаж не реагирует на посторонние звуки (бег-прыг) вне видимости. Слепой, очевидно, ничего не видит (но может поворачиваться на звук, а в боевом настрое даже бегать за источником шума). Слепой персонаж способен драться, если его на это спровоцировать, но только пока провокатор находится в непосредственной близости от слепого: малейшее удаление ведёт к потере цели.
Есть и независимые переменные, делающие глухими/слепыми сразу всех персонажей:
    ai2_deaf=[0/1]
    ai2_blind=[0/1]

    ai2_makeignoreplayer [персонаж] [0/1]
Персонаж игнорирует игрока. Аналогично, для массового игнорирования переменная:
    ai2_ignore_player=[0/1]

    ai2_idle [персонаж]
Даёт установку бездельничать. Обычно стоит перед следующей командой:

    ai2_setjobstate [персонаж]
Назначает текущее действие персонажа его работой. Используется для сброса всего остального в idle и для фиксирования, например, следующей вещи:

    ai2_dopath [персонаж] [путь]
Заставляет персонажа следовать данному пути (обычно патрульный обход по точкам в качестве работы, либо просто пробежка в заданной последовательности).

    ai2_doalarm [персонаж] [номер консоли]
Посылает персонажа нажимать указанную консоль. Не имеет значения, "тревожная" это консоль или "обычная" (на самом деле это почтиодни и те же консоли, просто в "тревожных" функциях, скриптовых же, характерное содержание. ну, и флажок для ИИ для поиска имеется). Более того, функции консоли имеют аргумент в имени имени нажавшего (что в оригинальных скриптах не используется), что можно использовать любым образом.

    chr_animate [персонаж] [название анимации]
Всё просто - персонаж выполняет заданную анимацию. Список анимаций равен списку TRAM. при этом нет никаких ограничений, на каком уровне анимация проигрывается, и соответствует ли данному персонажу, и т.д. Единственная неприятность - при проигрывании _tgt анимаций (жертвы бросков) иногда случается блам. Если ещё не исправлено. )
Суффикс _block традиционно приостанавливает выполнение функции до завершения анимации.

Для исполнения анимаций, циклично исполняющихся в течение переменного времени, следует воспользоваться более полным вариантом:
    chr_animate [персонаж] [название анимации] [длительность]
или
    chr_animate [персонаж] [название анимации] [длительность] [фактическое время]
В первом случае анимация просто будет длиться указанное время (нецикличные анимации тоже повторяются), во втором - анимация будет замедленной, чтобы исполниться в фактическое время (оно должно быть больше или равно длительности). При этом возникают различные побочные эффекты: например, персонаж может переместиться дальше, чем следует.

4. Прочее

4.1. Применительное к игроку

4.1.1. Геймплей
    lock_keys [клавиши]
Блокирует/разблокирует определённые клавиши, используемые игроком. Блокирует при отсутствии аргументов, разблокирует следующие типы: keys_reload, keys_hypo, keys_walk, keys_inventory, keys_action, keys_pause, keys_attack, keys_crouch, keys_jump, keys_movement. Для разблокирования всего сразу - keys_all.

    input [0/1]
Выключает/включает ввод игроком. В отличие от lock_keys, блокируется заодно и реакция на движение мыши.

    chr_aim_width=[число]
Угол (в градусах) поворота камеры (и головы игрока), по достижении которого игрок поворачивается всем телом. При 0~1 повоторов головы практически нет (лишь лёгкое подрагивание при повороте), при отрицательном значении модель будет постоянно потряхивать, при достаточно большом (>180) доступен практически полный оборот камеры вокруг вертикальной оси, однако при полуобороте возникает резкий поворот в "отражение" анимации. Стандарт - 70.

    chr_auto_aim_dist=[число]
Опредяет расстояние до противника, с которого работает "самонаведение" (практически мгновенный поворот точно в сторону цели) ударов. По умолчанию 40.

    chr_auto_aim_arc=[число]
Максимальный угол (в градусах) действия вышеуказанного наведения. По умолчанию 90, что, имхо, не очень удобно. Особенно страшно замечать за собой привычку предугадывать поворот и пытаться компенсировать эту функцию.

    chr_weapon_auto_aim=[0/1]
Отвечает за самонаведение оружия. Имеется ввиду автоматическое удержание прицела на противнике на ближней дистанции, но не "подсветка" прицела, когда он наведён на что-то живое.

    wp_force_no_scale=[0/1]
    wp_force_half_scale=[0/1]
    wp_force_scale=[0/1]
Отвечают за масштабирование прицела. =) При no_scale не масштабируется вообще (кажется, что вдали прицел большой, а вблизи не очень), при scale - сильно масштабируется (оч.большой прицел вблизи), half_scale - среднее и оптимальное.

4.1.2. Не геймплей
    gs_screen_shot_reduce=[число]
Уменьшает делаемые игрой скриншоты в 2^[число] раз. И правильно делает, для полноэкранных режимов.

    fall_back
Игрок падает назад.

    fall_front
Игрок падает вперёд.

    diary_page_unlock [номер]
Выблокировывает страницу данного номера в дневнике.

    chr_focus [номер персонажа]
Передаёт игроку заданного персонажа вместо 0. Не забывайте, что при подобной рокировке нужно тщательно контролировать ai2_takecontrol: и для прошлого персонажа (в частности, для самой 0 ИИ не предусмотрено), и для нового (чтобы не остаться в его теле под его контролем... или остаться)

4.2. Сохранения

    save_game [номер сохранения]
Сохраняет игру (местоположение, здоровье, инвентарь и т.п.) в соответствующий слот. Имеем ввиду, что слотов сохранения в каждом уровне можно иметь до десяти штук, и их вполне можно сделать динамическими (самое простое - по нажатию консоли).

    restore_game
Реализует данные из сохранения в игре. В бессюжетном, бессмысленном и беспощадном скрипте эта вещь необязательна, достаточно выполнять скрипт по ветке, зависящей переменной save_point

4.3. Получение констант

Переменной можно присвоить значение, возвращаемое функцией, но не наоборот. -_-
Помимо самописных функций с return, которые должны-таки работать, есть следующие встроенные функции:

    difficulty
Возвращает сложность игры (0 для простой, 1 для средней, 2 для сложной).

    did_kill_griffen (sic!)
Возвращает (из persist.dat) 1, если Гриффин был убит, 0, если нет.
Этот пункт можно вписать в persist.dat следующей командой:
    killed_griffen [0/1] (sic!)

    chr_is_player [персонаж]
Возвращает истинность того, является ли данный персонаж игроком (для баловства с chr_focus, например).

    chr_has_empty_weapon [персонаж]
Указывает на наличие у данного персонажа пустого оружия в руках (если оружие спрятано или его нет совсем, 0).

    chr_has_lsi [персонаж]
Отвечает за наличие у данного персонажа (не только 0) специального предмета (резак, ключи, и т.д.).

4.4. Ожидание.

Пока что нет возможности привязать функцию к какой-либо клавише и явно следить за какими-то очень конкретными событиями, но можно (обычно с помощью вилок) приостановить выполнение функции нижеследующими командами, дабы дальнейшее началось сразу по выполнении условия.

    chr_wait_health [персонаж] [количество здоровья]
Ждёт, пока здоровье персонажа не пересечёт заданное значение. Так как удары, падения, лечения гипами и chr_set_health работают плавно, ожидание довольно верное.

    chr_wait_animation [персонаж] [названия анимаций]
Ждёт, пока данный персонаж не начнёт выполнять данную анимацию (или любую из нескольких перечисленных). Традиционный аналог скриптового бинда и вообще интерфейса (а до появления консоли - ещё и её замена).

    chr_wait_animtype [персонаж] [типы анимаций]
Ждёт любую анимацию из целого класса (или даже нескольких классов) анимаций. Варианты: punch, kick, run, jump, flip, crouch, crouch_back, standing_turn_left, standing_turn_right, Pickup_Object, Pickup_Object_Mid, Pickup_Pistol, Pickup_Rifle, Pickup_Pistol_Mid, Pickup_Rifle_Mid, Autopistol_Recoil, reload_pistol, reload_rifle.

    wait_for_key
Ожидает нажатия чего-нибудь (что убирает начальную заставку уровня).
________________________________________________________________________________
В дальнейшем всё это будет дополняться и тем, что уже есть, но ещё не оформлено сюда, и тем, что надо просто перевести, и то, о чём будете спрашивать. -_-
На фактические ошибки, опечатки и просто спорные места указывайте, плиз. Они ведь есть, наверное, в немалом количестве...
Кинематику, катсцены, win-lose, dmsg-dprint и прочую неклассифицируемую фигню, которой хватать не будет, тоже перечисляйте. За алфавитным перечнем и на английские источники можно слазить, а тут вопрос в надобности команд... )

Огромное спасибо Амэ за огромное в составлении пособия участие. *_* И за мудрое руководство, пересилившее-таки мою лень. -_- Ну, и вообще... За всё. =)
И спасибо geyser'у за нижеоказываемую помощь и участие в составлении аналогичных англоязычных вещей.

iljaos » 24-07-2008 14:17:32

Спасибо всем людям которые писали это руководство, с ним-жить легче стало!

Mix@ ты писал о команде переносящей и грока в заданную точку на уровне. А где можно найти планы уровней с нужными единицами измерения?

Мih@ » 24-07-2008 14:56:18

iljaos, во-первых, в последний раз прощаю даблпостинг. В следующий раз буду стирать, не читая.
Во-вторых, подобные вопросы следует задавать в соответствующую тему, или хотя бы создавать новую, с перечислением претензий по недоработкам пособия, которых тут пока что предостаточно, но писаться дополнения будут в единую статью, а не рассредотачиваться по длинной теме, которых уже накопилось несколько штук.
В-третьих, планы уровней есть только в ресурсах игры.
Как описать векторы отсчёта на словах, или даже со скриншотом, без путаницы (а ведь уровни большие), я плохо себе представляю.
Сейчас допишу под chr_location простейший метод определения координат.

geyser » 26-07-2008 07:44:04

1.2.1
Mih@: "Скриптовые команды"
geyser: Фактически эти "команды" являются не чем иным, как вызовами функций (см. ниже). Слово "команда" я не люблю.
Mih@: chr_givepowerup [персонаж] [предмет] [количество]
geyser: Я бы и здесь ввёл понятие о типе параметров, то бишь: chr_givepowerup [string:персонаж] [string:предмет] [int:количество] / chr_givepowerup [int:script_ID] [string:предмет] [int:количество]
Mih@: "Собственно, принципиальной разницы я не вижу, но предпочитаю более традиционное написание - без скобок и с переносом строки в качестве разделяющего символа."
geyser: "Традиционный" синтаксис, он же "шелловый", не позволяет использовать в качестве параметра переменную.А это бывает нужно даже в Банькиных скриптах, не то, что в ОТА.

Остальное потом, по порядочку. Есть неточности, грубых ошибок пока не заметил.

Мih@ » 26-07-2008 09:45:02

geyser написал(а):

Слово "команда" я не люблю.

geyser написал(а):

тип параметров

Угу, это всё поправлю и дополню потихоньку.
Насколько я помню, например, sleep ведь относится к синтаксису и ключевым словам, а не к прочим "функциям"? Его "командой" можно обозвать? ) А то более подходящего слова не вижу... Как и ко всем "внутренним" функциям, которые хотелось отделить от тех функций, которые собственно и задаются в скриптах. Может, это не совсем правильно (но, имхо, и не совсем неправильно), да и вшитые функции можно переписывать в скриптах... Но, возможно, стоит просто уточнить в начале, что именно в контексте подразумевается под "командой", "строкой" и т.п.?

geyser написал(а):

"Традиционный" синтаксис, он же "шелловый", не позволяет использовать в качестве параметра переменную.

А вот это вот действительно забыл написать. О_о Хоть и собирался... Пасиба.

geyser написал(а):

Есть неточности, грубых ошибок пока не заметил.

И на том хорошо. +) Относительно... Дальше по ходу дела дописывать-исправлять буду...

geyser » 26-07-2008 10:57:36

sleep - единственное из ключевых слов, которое тянет на "команду" т.к. по употреблению похож на вызов функции.. У остальных - очень специфическое употребление, мало чего общего имеющее с "приказом". А поскольку оно одно такое, то не вижу причины использовать слово "команда" вообще. А ssg - вообще неправ.
Функции, предопределённые в движке, мало чем отличаются от пользовательских. Главное отличие - в движке разрешено некое подобие "перегрузки", т.е., тот же chr_givepowerup первым параметром может брать строку или целое число, и ведёт себя в обоих случаях по-разному. Пользователь такую функцию определить не может (а в C это равносильно определению двух одноимённых функций, что BSL опять же не позволяет). Плюс некоторые глюки в самом BSL, из-за чего пользовательские функции могут работать не совсем как надо (есть глюки с else, с return, и с обработкой строк - входных параметров функции). А так я бы не различал предопределённые функции и пользовательские. Философия вызовов, передачи параметров и т.п. для них для всех общая.

2.7
амбиент/музыка/диалог/импульс вызывается по имени OSBDkukareku.amb (амбиент/музыка/диалог) OSBDkukareku.imp (импульс)
Музыка и амбиент ничем не отличаются, кроме того, что у них разные регистры, поэтому если стартануть музыку как sound_ambient_start mus_fitec, то её и стопать надо как sound_ambient_stop mus_fitec
Диалог отличается от музыки и амбиента главным образом тем, что его нельзя "стоп". Общее у этих трёх то, что звук не локализован (то есть это всё по сути "амбиент").

Кстати о "стопе", вот пример "грубой неточности":

А тут еще кот выскочил к рампе и вдруг рявкнул на весь театр человеческим голосом:
? Сеанс окончен! Маэстро! Урежьте марш!!
Ополоумевший дирижер, не отдавая себе отчета в том, что делает, взмахнул палочкой, и оркестр не заиграл, и даже не грянул, и даже не хватил, а именно, по омерзительному выражению кота, урезал какой-то невероятный, ни на что не похожий по развязности своей марш.

Как видно в контексте, "урезать" (т.е. "врезать") - значит вовсе не оборвать на полуноте, а наоборот - "грянуть".

"Проигрывает некоторый блок реплик из диалога. Честно говоря, ни разу не видел блоков, кроме pause. =)"
Ни фига. Никаких "блоков". "pause" - это просто название диалогового звука, которого нет. Или разрабы лоханулись, или просто считали, что несуществующий звук писать лучше, чем никакого звука вообще. Короче, вызов sound_dialog_play kukareku откладывает воспроизведение диалогового звука kukareku до окончания текущего диалогового звука, только и всего.


1.2.4.
"Численные переменные ? любые числа, включая дробные (в меру: для очень дробных лучше использовать переменные с плавающей точкой) и отрицательные."
Ой. Мих, ты чё? Если твои "численные" - это инты, то какие на фиг умеренные дробные? Целые числа и ничего кроме. Причём чаще всего неотрицательные целые.

Мih@ » 26-07-2008 11:38:21

geyser написал(а):

Функции

Ну, с точки зрения представления в скрипте, строка ≈ команда ≈ вызов функции. А вызов функции и сама функция - вещи уже разной природы.
То бишь, имхо, про функции можно написать, например, так:
Функция
func void you_lose(string ai_name)
{
    sleep 240
    fade_out 0 0 0 180
    sleep 240
    lose
}

отвечает за эффект затухания экрана и проигрыш уровня.
А про вызов функции, соответственно, уже иначе:
Строка
    you_lose
отвечает за [то же самое].

Таким образом, обзывать строку, вызывающую функцию, самой функцией, имхо, не очень верно. Называть её "вызовом функции" тоже как-то некрасиво и неловко. А "строка" - понятие уже относительное, так как в саму по себе строку можно вместить и несколько вызовов. "Команда", подразумевающая "команду вызова функции", выходит наиболее приемлемым вариантом... Как мне кажется. -_-

geyser написал(а):

Музыка и амбиент ничем не отличаются, кроме того, что у них разные регистры, поэтому если стартануть музыку как sound_ambient_start mus_fitec, то её и стопать надо как sound_ambient_stop mus_fitec

Угу. А какого-нить списка в сети о том, что .imp, что .amb, нету? Или просто отправлять всех читать OSBD в ресурсах?..

geyser написал(а):

Кстати о "стопе", вот пример "грубой неточности"

Угу. )

geyser написал(а):

Ни фига. Никаких "блоков".

Угу. Хотя не совсем угу. _block ведь вроде должен тормозить выполнение всего, что после этой строки? А не только диалоговых функций?

geyser написал(а):

Ой. Мих, ты чё?

Воистину ой. А ещё там про float вообще ни слова не было изначально. )) Щас пофиксю всю эту ересь...

geyser » 26-07-2008 13:08:47

Слово "строка" я тоже не люблю, т.к. из-за него у народа путаница между "строчками" кода и значениями типа string. Советую употреблять слова "инструкция" (statement) и "выражение" (expression) для базовых элементов кода.
Слово "инструкция" - по сути та же "команда", но под это понятие подпадают и сложные инструкции (фигурные скобки), и условные инструкции (if ... else), и декларации/определения переменных/функций, и присвоения переменных, и вызовы функций.
"выражение" - слово менее общее. Это нечто, имеющее значение. У присвоения значение как бы есть, и у вызова функции - тоже, а вот у сложной инструкции, или у определения - скорее нет.

"Таким образом, обзывать строку, вызывающую функцию, самой функцией, имхо, не очень верно. Называть её "вызовом функции" тоже как-то некрасиво и неловко."
С первым согласен, со вторым - нет. Вызов функции - он вызов функции и есть. Ничего неловкого, всё строго и справедливо. Есть функция, и мы её вызываем.

"А какого-нить списка в сети о том, что .imp, что .amb, нету? Или просто отправлять всех читать OSBD в ресурсах?"
1007 *.amb, 298 *.imp ... Дамп имён всей этой толпы нисколько не удобнее читать, чем просто перечень .oni-файлов в Windows Explorer или Total Commander... особенно если грамотно рассовать звуки по папочкам и подпапочкам. OniSplit позволяет. Всем рекомендую. Музыку продокументировал здесь, когда был маленький и глупый: http://wiki.oni2.net/Music/Ingame

"_block ведь вроде должен тормозить выполнение всего, что после этой строки? А не только диалоговых функций?"
Тормозит-то он тормозит, но именно что "блокирует" данную инструкцию (и естественно всё, что после неё - это просто последовательное выполнение BSL), а "блок инструкций" здесь ни при чём.

Мih@ » 26-07-2008 13:49:34

geyser написал(а):

Советую употреблять слова "инструкция" (statement) и "выражение" (expression) для базовых элементов кода.

Ок.

geyser написал(а):

Вызов функции - он вызов функции и есть. Ничего неловкого, всё строго и справедливо. Есть функция, и мы её вызываем.

Говоря строго и справедливо, вызов - это вообще скорее процесс. Есть набор символов в скрипте, который инициирует (ну, вернее, заставляет инициировать того, кто этот набор символов исполняет) вызов функции. Есть функция, которая вызывается тем набором символов. А сам вызов - это нечто между ними, или то, во что они входят. Инструкция > вызов > функция. Инструкция пишется в консоль, функция вызывается, а сам вызов - это нажатие ентера и последующие процессы. Либо инструкция пишется в .bsl файл и мирно дожидается своей минуты, а вызов происходит, когда скриптовый движок эту инструкцию читает и выполняет. Обозвать кучу буковок вызовом у меня как-то в принципе язык не поворачивается... Только то, что эта куча буковок делает при своём исполнении. Как-то так.

geyser написал(а):

Дамп имён всей этой толпы нисколько не удобнее читать, чем просто перечень .oni-файлов в Windows Explorer или Total Commander...

Зато, может, чуть удобнее, чем по dir | more... Проблема устарела уже, это во времена IRF_Oni в куче SNDD было почти невозможно ориентироваться...  Да и сейчас, имхо, закономернее и логичнее будет текстовый список читать, нежели только ради этого списка вываливать кучу мусора в какую-нить директорию и затем постоянно к ней обращаться. Файлы ж всё равно никуда не денутся. По крайней мере, из более-менее оригинальных ресурсов...

geyser написал(а):

http://wiki.oni2.net/Music/Ingame

Угу, заодно ссылку сюда вставлю эту... )

geyser написал(а):

"блок инструкций" здесь ни при чём.

Я в курсе, только проникся смыслом всех _block'ов немножко позже, чем написал единственную пришедшую в голову догадку относительно этого суффикса, так как ни chr_animate_block, ни cm_[...]_block особо не пользовался, отдавая всё всемогущему sleep'у. А при вызове отдельной инструкции из консоли разницы с и без _block как бы и нету... При переписывании в cm_ эти блоки поправил, а вот диалог проглядел почему-то...

geyser » 26-07-2008 14:47:09

"вызов - это вообще скорее процесс" Тоже мне философ нашёлся...  Все програмисты называют такой вид инструкции вызовом (call), и ничего, никакой путаницы. Если ты отвлечёшься от BSL или C и глянешь в машинный код, то там ты может и по-другому заговоришь: там вызовы имеют свою трактовку, на другом уровне. Но в рамках языка BSL:  dmsg("пусть меня покрасят") есть не что иное, как инструкция - вызов функции dmsg с параметром/аргументом - строкой "пусть меня покрасят".

"Да и сейчас, имхо, закономернее и логичнее будет текстовый список читать, нежели только ради этого списка вываливать кучу мусора в какую-нить директорию и затем постоянно к ней обращаться."
Всё равно не понимаю. Есть OniSplit. Он разворачивает ресурсы так, что OSBD аккуратно лежат рядышком, причём их можно аккуратно разложить по папочкам: музыку туда, диалоги сюда, шаги ещё куда-нибудь, шумы всякие... При паковке OniSplit это всё съест и не поморщится, а у пользователя возникает удобная классификация этих самых звуков. Люди смотрят на такую директорию, и сразу видят, какие бывают OSBD. Если они хотят копнуть поглубже - открывают OSBD в редакторе или через OniBrowser и сразу имеют инфу о том, с чем данный OSBD едят.
Кому будет лучше от того, что я всё это высеку на мраморе? Не лучше ли просматривать директории или использовать OniBrowser, и иметь реальную информацию о текущем ассортименте OSBD?

"Файлы ж всё равно никуда не денутся. По крайней мере, из более-менее оригинальных ресурсов..."
Я бы на это не сильно рассчитывал. Мне в последнее время влом документировать "каноническое" содержание Они (всякие вот эти списки), потому что при мало-мальски мотивированных моддерах это всё станет давно и неправда (да уже неправда, посмотреть хоть на самые базовые фиксы в Эдишне). А обслуживать леймеров, которые будут в своём углу моддить исходную версию - не вижу причины =)

Мih@ » 26-07-2008 15:24:28

geyser написал(а):

Тоже мне философ нашёлся...  Все програмисты называют такой вид инструкции вызовом (call), и ничего, никакой путаницы.

Ну, значит, вызов как процесс есть calling от statement'а к function'у, и call ≠ statement. Иначе выходит, что сам вызов и вызывает вызываемое. @_@ Не инструкция есть вызов, а инструкция означает, подразумевает, характеризует вызов. В машинном коде, может, это и одно и то же, но ведь речь-то о bsl. ) Впрочем, ладно, уболтал, вызов так вызов, всё равно команды теперь будут называться инструкциями. )

Про OSBD - тоже угу. Примерно поэтому же и пособие это волочилось еле-еле и едва ли не завяло в начале, что возник вопрос - а зачем вообще расписывать обыкновенные скрипты, функции и особенности наряду с наиболее приближёнными частями оригинальных ресурсов, если всё это скоро начнёт мутировать от гораздо более глубоких модификаций? Когда будут новые оружия и противники, когда почти все ресурсы станут доступны из любого уровня, кинематических мордашек станет в пять раз больше, появятся два новых кавайных цвета для dmsg, новые виды предметов, новые уровни, новые скриптовые функции, наконец, новый движок и новый вид скриптов, например, на том же lua? С одним только девмодом львиная доля скриптовых ухищрений стала выполняться в два счёта прямо из игры, если не нажатием одной-двух хоткеев. Не говоря уж о всплывающих подсказках и консольной ругани, по которой можно заиметь представление о немалой части функций... Другое дело, что в крайности впадать не следует, раз пока что хотя бы часть из этого кому-нибудь да понадобится... )

geyser » 26-07-2008 15:47:54

"Ну, значит, вызов как процесс есть calling от statement'а к function'у, и call ≠ statement." Нда, неглупый малый, но педант.
Вызов есть частный случай инструкции, наряду с: определением, присвоением, блоком {}, sleep-ом, if-ом, return-ом...

"С одним только девмодом львиная доля скриптовых ухищрений стала выполняться в два счёта прямо из игры" Именно поэтому я рекомендую преподавать BSL в первую очередь на примере консольного ввода. Уж зашитые-то функции с консоли вызывать - самое милое дело... Всё можно наглядно так объяснить.

"а зачем вообще расписывать обыкновенные скрипты, функции и особенности наряду с наиболее приближёнными частями оригинальных ресурсов, если всё это скоро начнёт мутировать от гораздо более глубоких модификаций?"

Это не совсем одно и то же. BSL - вещь мощная и как язык гораздо более элементарная и неизменная чем коллекция данных - ресурсов. Если ресурсы вроде OBJC подлежат массовому апгрейду, который лишает смысла дотошную документацию - то BSL уже сейчас практически достаточен для Эдишна. Не хватает марафета для сингл-плеера, ну и кое-каких вкусностей для арены. А так всё есть, и конечно же никто не собирается на фиг переопределять или отменять знакомые ключевые слова или функции. Вот так вот... даже совсем не одно и то же.

Мih@ » 26-07-2008 16:11:20

geyser написал(а):

Вызов есть частный случай инструкции

Что он есть частный случай, само собой, вопрос был в том, сама ли это инструкция, или то, что она делает, за что отвечает и для чего вообще нужна. Т.е. не инструкция-вызов, инструкция-присвоение, инструкция-возврат, а инструкции вызова, присвоения и возврата. Ладно, не надо берданку, я понял уже всё. %)

geyser написал(а):

Именно поэтому я рекомендую преподавать BSL в первую очередь на примере консольного ввода.

А в таком случае не теряется большая часть смысла скриптов?.. Ну, то есть, это уже получается пособие к консоли, а для скриптов, напротив, надо будет упор сделать на том, что можно и нужно делать только ими, используя консоль максимум как дебаггер с dprint'ами и руганью об ошибках, или как инициатор каких-нибудь функций, без извращений с chr_wait_anim*...

geyser написал(а):

BSL уже сейчас практически достаточен для Эдишна.

Хм, ну раз он ещё таким долго будет, то хорошо. о_О Значит, есть в этом какой-то смысл. ) И даже немалый... О_о

geyser » 26-07-2008 19:11:18

Смысл консольного скриптинга в том, чтобы быстро и непринуждённо прочувствовать, как конкретно работают ключевые функции. Сложные конструкции, конечно, никто с консоли вбивать не будет (хотя заскриптить заготовку и вызывать с консоли - тоже вполне педагогический ход). Главное - чтобы у народа было как можно меньше мистики по поводу эффекта той или иной функции/переменной. Чтоб параметрами владели свободно. С каждой функцией на ты. А это как раз очень естественно достигается путём консольного скриптинга.

@ вызов: :"неглупый малый, но..." Говорю же тебе - между вызовом-процессом и вызовом-инструкцией никогда не было никакой путаницы. Потому, что говорить об абстрактном "процессе вызова" редко кому приходится - и наоборот, синтаксическое понятие вызова как структуры языка - точно определено и широко употребляемо. Если уж на то пошло, то Онька первым делом убирает из скрипта все комменты, табы, энтеры и пробелы, кое-что разворачивает, кое-что подставляет... Мы же не будем и для этой промежуточной стадии отдельную терминологию придумывать? правильно - в гробу мы её видали... Поскольку всё тождественно, какая разница: имеем мы дело с "процессом вызова" или его причиной/отображением в скрипте? есть ведь разница? правильно - если мы глядим в скрипт и соответственно имеем дело с человекочитабельными буковками, то нам естественно всю жизнь движка описывать в рамках этого самого языка из буковок, а не каких-то там последствий, которыми эти буковки чреваты, т.е., не выходить за рамки нашего главного инструмента - языка. И поэтому мы будем называть вызовом функции соответствующую инструкцию в текстовом файле, а не соответствующее движение сфер в рантайме. Рантаймовые мистерии - не скриптерого ума дело, и не хрен мозги сушить.

demos_kratos » 25-08-2008 20:33:52

насколько я понимаю, всё, что здесь обозвано "командами" - не что иное, как процедуры, а вот функции, возвращающие какое либо значение в игре есть? можно ли их задать самому?

Мih@ » 26-08-2008 03:30:04

demos_kratos написал(а):

насколько я понимаю, всё, что здесь обозвано "командами" - не что иное, как процедуры, а вот функции, возвращающие какое либо значение в игре есть?

В bsl (как и много где ещё) принципиальных отличий между функциями, которые что-то возвращают, имеют аргументы и пр. от void нету. В синтаксисе самих функций. Так, на всякий случай. )
Возврат значений существует, конечно, но особого в нём смысла я не вижу, ибо безжалостен к памяти и не брезгую создавать временные переменные (кто видел rh3, тот особенно хорошо поймёт, гы-гы). Но, если хочется шибко красивого кода, то вполне возможна строчка вида:
    [переменная] = [функция]([аргументы]);
С тем, как и чего именно происходит возврат, я пока толком не разбирался, экспериментальные наблюдения (в функции, значение которой присваивалось переменная, только три операции присвоения из трёх обычных переменных, включая искомую, и одной внутренней) таковы:
1) на выход идёт значение от последнего присвоения (var1 = var2 + 56 => var1, он же (var2 + 56), на выход).
2) если есть return(varx);, то на выход идёт varx, а функция дальше return'а не едет.
3) если есть просто return без аргументов, то его как бы и нет (функция едет до конца, выход по пункту 1).
Из возвращалок в игре мне казалось, например, что did_kill_griffen - не константа read-only, а bool-функция...

geyser » 26-08-2008 21:51:32

Если мне не изменяет безжалостно затраханная Михой память,
движок определяет только 5 "функций" (в паскалевом смысле):

bool did_kill_griffen()
bool chr_has_lsi()
bool chr_is_player()
bool chr_has_empty_weapon()
int difficulty()

Остальные влияют на состояние игры либо выводят что-то на печать.
Как видишь, demos_kratos, раздолье весьма умеренное... Се ля ви.

Кроме того, ключевое слово return принадлежит к больным местам BSL.
Целые числа возвращать получается, а вот строки - скорее как бы нет.
Другое больное место - else, а также парсинг строк в условиях для if.

iljaos » 12-01-2009 15:16:52

Извините конечно, что поднимаю старую тему но в пособии написано "В принципе, количество здоровья не ограничивается никакими разумными рамками, но всё здоровье, превышающее верхнюю границу даоданавой силы, отображается как равное верхней границе, и соответствует аналогичной даодановой силе.

"В принципе, количество здоровья не ограничивается никакими разумными рамками". Это так но у меня больше 1 и 31 нуля, поставить нельзя. Коноко просто умрёт. Может это у меня одного так, но наверняка нет. Я вводил chr_set_health 0 1 и при постановке тридцати двух нулей, игра заканчивалась смертью. Будьте бдительны!!

awp_master.pro^no clear* » 12-01-2009 15:25:09

погоди,но ведь я думаю никому не нужно ставить 32 нуля,это глупо,легче ввести liveforever.А то что тебя не ограничивают,так это правда,ставь какие угодно числа,но команда ведь работает

geyser » 12-01-2009 22:54:58

Строка, зарезервированная движком для каждого входного параметра, ограничена 32-мя символами, считая с конца.
Поэтому "100000000000000000000000000000000" - это всё равно, что ноль. А "700000000000000000000000000000042" - всё равно, что 42.
Кстати, iljaos, в Михином учебнике упомянут твой любимый глюк в правом кольце гуя (если жизни, щит, или маска превышают разумные границы).

iljaos » 13-01-2009 13:21:33

geyser спасибо уже в который раз =)

awp_master.pro^no clear* я конечно понимаю, что тебе доставляет удовольствие меня поправлять но все же будь по внимательнее. Никто и не спорит, я просто провел исследование, я уже писал что при постановке в chr_set_health большого числа я умер. Вот и решал заняться, вижу что никто не замечал этого.:)

awp_master.pro^no clear* » 13-01-2009 13:50:49

Извиняюсь,я никого не хотел обидеть......,ладно буду писать в тему

geyser » 14-01-2009 17:43:44

Извините за недержание флуда, но всё-таки awp_master.pro^no clear* был прав.

iljaos - важно понимать, что такое большие числа. Даже лосю известно, что хелсы в состоянии оверпауэра спадают быстрее, чем один хелс в секунду, но медленнее, чем в секунду 60 хелсов - иначе стандартного оверпауэра (200 сверх нормы или около того) хватало бы на долгие минуты или считанные секунды, соответственно. Допустим, для наглядности, что десять хелсов спадают за три секунды (на самом деле - 60 хелсов за 11 секунд, то есть примерно 5 хелсов в секунду). Тогда 10^32 (единичка и 32 ноля) пропадут за 30*10^30 (тройка и 31 нолик) секунд. Это - тридцать квадрильонов квадрильонов секунд. Или 30 тысяч миллиардов миллиардов миллиардов. Красиво, но ежу по-прежнему непонятно, много это или мало. Что делать?

Начинаем считать секунды. В одном часу их всего-то 60х60=3600, так что до тысячи в наше время не досчитает только ленивый. А до миллиона - шесть нолей - далеко? Оказывается, порядочно. В году (365 дней по 24 часа и ещё 6 часов) секунд наберётся 31557600, то есть тридцать миллионов, то есть до миллиона - шесть нолей - мы будем считать дней эдак двенадцать - это уже надоедает. А миллиард секунд - девять нолей - это уже тридцать лет. Триллион секунд - двенадцать нолей - 30 тысяч лет. Квадрильон - пятнадцать нолей - 30 миллионов лет, тут уже динозаврами попахивает. А квинтильон - всего-то восемнадцать нолей, казалось бы, плешь собачья - это 30 миллиардов лет. Для сравнения, возраст матушки Земли оценивается в 4 с половиной миллиарда лет, а возраст Вселенной - в 18 миллиардов. Дальше считать - ежу не хватает воображения.

То есть - грубо говоря, в нашем приближении, за год съедается 100 миллионов хелсов (восемь нолей), а со времён динозавров, за сто миллионов лет, съелось бы 10 миллионов миллиардов хелсов (16 нолей). А 32 ноля - это ещё на столько же умножить. Так что, iljaos, прочувствуй разницу между твоими Онишными сейшнами и возрастом динозавров "в квадрате". Единичка и 32 нуля - это тебе не хухры-мухры.

Кроме того, нетрудно проверить, что число с 32-мя десятичными знаками без труда перешибает максимальное представимое в машине 32х-битное целое число, то есть 4 294 967 295 (даже 64х-битное перешибает, которое 18 446 744 073 709 551 615). Что это значит? Это значит, что хелсы персонажа могут иметь значение только от 0 до 4 294 967 295 включительно, а любые числа, выходящие за этот диапазон, делятся с остатком на 4 294 967 296, и хелсы приравниваются к вот этому остатку. То есть, если ты напишешь chr_set_health(0, 4294967300), то новые хелсы Коноки будут мизерные - 4 очка. Добавляя твои любимые нолики, ты всего лишь изучаешь остаток деления Очень Круглых Десятичных Чисел на Очень Круглое Двоичное Число 4 294 967 296.

Итак, мы поняли, что самые большие и долгоиграющие хелсы получаются, если вбить chr_set_health(0, 4294967295), или - что то же самое, но запоминается проще и вбивается быстрее - chr_set_health(0, -1). В переводе на человекочасы это даёт - умножаем на 11 (фрэймы), делим на 60 (секунды), ещë на 60 (минуты), ещё на 60 (часы), ещё на 24 (дни) и ещё на 365,25 (годы) - 25 лет. Даже если врубить fast_mode, который ускоряет игровое время в 10 раз и делает игру невозможной - даже тогда этого хватит на 2 с половиной года.

Так что с большими числами, iljaos, надо дружить, а то они на нашей с тобой могиле что-нибуть такое станцуют.

P.S. А, да. Предупреждение экспериментаторам. Если засетить ai2_showhealth=1, то движок для каждых пяти хелсов рисует чёрточку у каждого чела над головой. Если Конока одна и хелсов у неё, скажем, пять миллинов - это миллион чёрточек, и серьёзная нагрузка для движка. Если сделать максимальные хелсы - 4 миллиарда - то при отображении чёрточек Онька просто повиснет.

iljaos » 17-01-2009 08:55:11

Я уже давно понял что с числами надо дружить. По идее тема поднималась что бы уведомить народ. Понимаю, что единицу с 32 нулями никто ставить не будет, но зачем тогда форумы существуют??? Я и awp_master.pro^no clear* по идее сказал это же самое. Просто дополнение или пояснение как хотите называйте, информация нужна всем, вот посмотрит кто нибудь из тех кто первый раз играет в эту игру, и поймет что хоть и liveforever существует, но с chr_set_health шутить не стоит

geyser » 17-01-2009 11:28:51

Ты лучше скажи - ты усёк, что от  chr_set_health(0, 4294967296) тоже умирают?
( а от 33х-значного 100000000000000000000000000000400 - наоборот - нет )
И что на сутки непрерывной игры хватает chr_set_health(0,500000)? =)

awp_master.pro^no clear* » 17-01-2009 11:49:44

всмысле на сутки?я че через сутки сдохну?а если уровень пустой,не одного перса,кто меня килл?а если в уровне 32 муро с 100000000 хп?

Добавлено спустя 1 минуту 1 секунду:
насчет 100000000000000000000000000000400 оно и понятно,у нас 400 хп

iljaos » 17-01-2009 17:46:59

geyser с твоими профессиональными объяснениям, становится почти все понятно.

awp_master.pro^no clear*  ты про 32 муро пошутил, что ли???

awp_master.pro^no clear* » 17-01-2009 17:59:18

НЕ ПОНЯЛ ПРИ ЧЕМ ТУТ 32 МУРО

geyser » 17-01-2009 18:04:07

awp, "хватит" это не в смысле через день сдохнешь, а через день оверпауер кончится. От противников при таких масштабах зависит не очень сильно. Если ты специально не подставляешься под самые болезненные удары, урон от противников несоразмерим с потерей 5 хелсов в секунду. А 32 перекачанных Муро бьют всего-то в 2.3 раза больнее обычного.
Я думаю, самое важное - помнить, что максимальное 32-х битное неотрицательно целое число - это 4 миллиарда с копейками. И что, поскольку оно неотрицательное, то по модулю (остатку) оно равно -1. Если не нравится минус-единица и есть претензии к полумиллиону, можно вбивать миллиард - его уж точно хватит на годы.

Я думаю, самое важное - помнить, что максимальное 32-х битное неотрицательное целое число - это 4 миллиарда с копейками. И что, поскольку оно неотрицательное, то по модулю (остатку) оно равно -1. Ну и заодно помнить, что 4 миллиарда - это 20 лет оверпауера или 2 года фазовой маски.
Если не нравится chr_set_health(0,-1) и есть претензии к полумиллиону, можно вбивать миллиард - его уж точно хватит на годы.

Ну и конечно, все эти соображения о том, что такое много-мало, можно обобщить на другие неотрицательные целые в Они. С 32-х битными мы разобрались, но есть, в принципе, и 16-битные, максимальное значение которых - 65535. Это уже гораздо меньше часа, если мерить во фреймах. Минут эдак 18. Кроме того, числа бывают со знаком, а это уменьшает максимальное положительное значение вдвое.

iljaos » 17-01-2009 18:05:15

"а если в уровне 32 муро с 100000000 хп?"
Вот я и спросил, в шутку пошутил ты или нет. Ведь никому в голову не придёт такой уровень не проходить. Хотя отъявленным геймерам может и придти

KindMuro » 15-06-2009 13:28:42

Ээээ, вдруг в директории с игрой нашел текстовый файл с описанием всех скриптовых команд - что-то раньше я его не замечал. Или я его скопировал откуда-то...
command: ai2_comehere
desc: tells an AI to come to the player

doktordulit » 15-06-2009 18:45:47

Наверняка с консоли до этого вбивал dump_docs...

KindMuro » 20-06-2009 18:53:14

Наверно, но вот не помню точно.

Manticore » 03-07-2009 13:30:33

Мih@ написал(а):

1.1.1. Что такое скрипты, для чего они нужны?
Это командные сценарии, выполняемые в игре. С помощью них вы сможете изменять и разнообразить геймплей.

я не могу сделать новые сценарии? я могу менять только те сценарии, которые заложены в игру?

AWP_Mega » 03-07-2009 13:35:37

Manticore написал(а):

я не могу сделать новые сценарии? я могу менять только те сценарии, которые заложены в игру?

Поподробнее,видимо ты не так понимаешь слово "сценарии",Сценарии-это понятие растяжимое...

Manticore » 03-07-2009 13:53:41

chr_teleport 0 7010
    sleep 120
    win
тут написано "маи телепортируется в указанную точку и победа". А если я напишу (я образно скажу):
Chr_givepowerup
tank_spawn_guns.
То есть я написал новый сценарий "около Маи появится танк с двумя пушками." Я просто меняю значения в игре с помощью скриптов и не более?

AWP_Mega » 03-07-2009 13:58:28

Впринципе да,только команд для этого потребуется намного больше

Manticore » 03-07-2009 14:07:27

Умение написания скриптов поможет в создании мультиплеера или Oni-2? мне кажется что нет.

AWP_Mega » 03-07-2009 14:08:22

Manticore написал(а):

Умение написания скриптов поможет в создании мультиплеера или Oni-2? мне кажется что нет.

Умение писать музыку тем более...

Manticore » 03-07-2009 14:18:57

AWP_Mega написал(а):

Умение писать музыку тем более...

но тогда будет Oni-2 без музыки, а это уже другая Оня...

AWP_Mega » 03-07-2009 15:38:41

Manticore написал(а):

Умение написания скриптов поможет в создании мультиплеера или Oni-2? мне кажется что нет.

Мда,похоже ты не очень дружишь с программированием,дело в том,что не существует нормальной игры,в которой не было бы скриптов,скрипты это как скелет...

Manticore » 03-07-2009 17:10:51

AWP_Mega, "уметь написать скрипт" здесь означает "уметь составить из функций и команд скрипт". А для того чтобы написать мультиплеер или Oni-2 нужно уметь делать сами функции и команды. Пособие, описанное выше, не учит делать игры. AWP_Mega, ты говорил что делал скрипты. Ты их делал из готовых функций и команд, а как я понимаю, для создания игры нужно уметь делать сами функции и команды.

Мih@ написал(а):

Персонажей из одного уровня нельзя переместить в другой уровень

это значит что нельзя играть за Барабаса или Мутанта-Муро в любой миссии?
if (my_save_point eq 1)
    {
# this is a built in save point for
        can_train_movement=0;
#        objective_set(1)
        door_lock(15);
        door_lock(16);
        particle(lock1_locklight01, do, stop);
        restore_game
        ai2_spawn Barabus
        playback 0 SwingBarabusSet
        target_set(1,0.0)
        dprint RESTORE_SAVE_Point_1
        splash_screen warehouse_splash_screen
        swing_cutscene

Я написал "ai2_spawn Barabus" (для первой миссии) но Барабас не появился! Почему?

doktordulit » 03-07-2009 17:44:00

Вопервых,его нет в BINACJOBCharactes
Вовторых,игра по твоему читает твои мысли?И он появится там где ты подумал?

AWP_Mega » 03-07-2009 17:45:29

Manticore написал(а):

Я написал "ai2_spawn Barabus" (для первой миссии) но Барабас не появился! Почему?

УУУ,начнем с того что ты даже не указал телепорт барабаса,а откуда ему там взяться?Это для начала займись глобализацией
Блин,doctordulit,прочитал мои мысли =)

Manticore » 03-07-2009 17:46:39

А где и что надо написать, чтобы я мог играть за Барабаса? Спасибо!

AWP_Mega написал(а):

займись глобализацией

чем?

AWP_Mega » 03-07-2009 17:47:52

И это ты собрался нами руководить =|

Manticore » 03-07-2009 17:52:02

AWP_Mega написал(а):

И это ты собрался нами руководить

я не собирался руководить, я говорил что мой брат может руководить.
Мне надо повнимательнее почитать FAQ-пособие? А что ещё почитать?

AWP_Mega » 03-07-2009 17:53:06

Manticore написал(а):

А что ещё почитать?

Если скучно,можешь на централе прочитать про сплит и ОУП,я так когда-то и сделал

doktordulit » 03-07-2009 17:53:58

AWP_Mega написал(а):

Блин,doctordulit,прочитал мои мысли

You dont know what I alredy know))))))))))

Мih@ » 24-07-2009 19:10:11

первый пост немного обновлён и ещё будет обновляться.
все возникающие вопросы по скриптам - не сюда, а туда. предварительно тщательно обдумав, так ли сложен и важен возникший вопрос, что с ним нельзя разобраться самостоятельно.
здесь - только обсуждения по сути первого поста.

AWP_Mega » 28-07-2009 20:17:42

Вообще не понимаю по какому принципу действует блокировка клавиш,хочу поставить допустим античит(f1 убрать)Ввожу lock_keys fkey1 но ничего не происходит,вижу у вас перед самими действиями стоит keys_ и как догадаться что ввести после?Да и вообще часто замечаю что нужны номера(флаги,страницы дневника и т.д)Где взять-то?Ссылки не видел..Да и с followme не все ясно,работает только тогда,когда захочет

geyser » 28-07-2009 21:38:09

Вот здесь описаны группы кнопок, подчиняющиеся команде lock_keys: http://wiki.oni2.net/Customizing/Bindin ... ble_events
Чтобы разобраться с тем, как именно работает команда lock_keys, поучительно изучить тренировочный скрипт для EnvWarehouse.

Вот здесь перечислены индексы флагов в уровнях игры-оригинала: http://geyser.oni2.net/OBD/BINA/OBJC/FLAG/
Просматривать их удобнее всего через OniMenu: http://geyser.oni2.net/OniTeamArena/tools/global/
Или через специальные скрипты FlagViewer: http://zdlo.oni2.net/Scripts/DeveloperMode/FlagMap/

К страницам дневника разве приходится обращаться из скриптов? И что такое "и т.д."? =)

AWP_Mega » 28-07-2009 21:48:28

Спасибо за ответ и ссылки

geyser написал(а):

К страницам дневника разве приходится обращаться из скриптов?

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

geyser написал(а):

И что такое "и т.д."?

Сначала хотел написать про названия команд,номера дверей и консолей,но вдруг вспомнил про stuff

Мih@ » 29-07-2009 05:31:20

AWP_Mega написал(а):

lock_keys

Мih@ написал(а):

4.1.1.
    lock_keys [клавиши]
Блокирует/разблокирует определённые клавиши, используемые игроком. Блокирует при отсутствии аргументов, разблокирует следующие типы: keys_reload, keys_hypo, keys_walk, keys_inventory, keys_action, keys_pause, keys_attack, keys_crouch, keys_jump, keys_movement. Для разблокирования всего сразу - keys_all.

?

AWP_Mega написал(а):

followme

Мih@ написал(а):

ai2_comehere [персонаж]
    ai2_followme [персонаж]
Посылают персонажа идти к точке, где стоял игрок на момент вызова этой функции. ai2_followme должна была бы регулярно уточнять текущее расположение игрока, но не делает этого из-за небольшой скосяченности. Для не самых замороченных случаев можно воспользоваться аналогом типа:
var bool follow;
func followme(string ai_name, int step)
{
    ai2_comehere(ai_name);
    sleep(step);
    if(follow) fork followme(ai_name,step);
}
Где follow=1; followme [персонаж] [период обновления координат] позволяет включить следование, а follow=0; - выключить.

??

AWP_Mega написал(а):

некими командами можно разблокировать и заблокировать страницы дневника

Мih@ написал(а):

diary_page_unlock [номер]
Выблокировывает страницу данного номера в дневнике.

???

AWP_Mega написал(а):

Сначала хотел написать про названия команд,номера дверей и консолей,но вдруг вспомнил про stuff

Мih@ написал(а):

Список дверей по уровням с номерами, названиями, скриншотами, изначальными положениями и названиями сопутствующих индикаторов можно взять на OniStuff.

Мih@ написал(а):

Список консолей во всех уровнях с номерами, скриншотами и вызываемыми функциями можно взять на OniStuff.

????

что неясно?
вот про задания в F1 не написано, да. потому что они не просто через objective_set делаются, а имеют привычку в оригинальных скриптах быть вынесенными в отдельные функции set_objective_# (также, как выносятся сохранения и win/lose). и это, наверное, надо как-то на всякий случай подчеркнуть, и объединить если не с trigvolume_enable, то с target_set уж точно.

про способы осмотреть флаги, видимо, надо будет дописать, например, около chr_teleport.

geyser » 29-07-2009 05:48:07

ai2_followme должна была бы регулярно уточнять текущее расположение игрока, но не делает этого из-за небольшой скосяченности

Насчёт "небольшой скосячености" можно поподробнее, или это суть домысел?

diary_page_unlock [номер] Выблокировывает страницу данного номера в дневнике.

Нда? А если я попрошу предъявить рабочий пример применения этой функции?

Мih@ » 29-07-2009 06:10:48

geyser написал(а):

Мih@ написал(а):

ai2_followme должна была бы регулярно уточнять текущее расположение игрока, но не делает этого из-за небольшой скосяченности

Насчёт "небольшой скосячености" можно поподробнее, или это суть домысел?

geyser написал(а):

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

если и домысел, то не мой. )

geyser написал(а):

Нда? А если я попрошу предъявить рабочий пример применения этой функции?

да, переформулировать и доуточнить стоит... пример - ну, например, для шестой главы. имеем один "learned move page" про kick_heavy и "normal page" про нападение.
    diary_page_unlock 0 - страницы закрыты
    diary_page_unlock 1 - открыто kick_heavy
    diary_page_unlock 2 - страницы открыты
то бишь, открытие сугубо последовательное и отсчёт ведётся локально для каждого уровня. больше дополнительных записей - больше вариантов. например, при нелинейном прохождении найти сокрытую страницу (например, привязать в 9 главе к консоли про Гриффина). или не найти.

AWP_Mega » 29-07-2009 08:49:42

Мih@ написал(а):

что неясно?

Все что было не ясно уже geyser обьяснил

Добавлено спустя 2 минуты 41 секунду:

geyser написал(а):

AWP_Mega написал(а):

    Сначала хотел написать про названия команд,номера дверей и консолей,но вдруг вспомнил про stuff

    Мih@ написал(а):

    Список дверей по уровням с номерами, названиями, скриншотами, изначальными положениями и названиями сопутствующих индикаторов можно взять на OniStuff.

    Мih@ написал(а):

    Список консолей во всех уровнях с номерами, скриншотами и вызываемыми функциями можно взять на OniStuff.

Ты мог заметить,что я сначала написал,а потом вспомнил

Мih@ » 29-07-2009 09:00:54

AWP_Mega написал(а):

Все что было не ясно уже geyser обьяснил

интересно, что вообще эти вопросы делали в теме, где раскрыты первым постом. =\

AWP_Mega написал(а):

Ты мог заметить,что я сначала написал,а потом вспомнил

учитывая, что во всё том же посте в соответствующих пунктах указаны ссылки туда...

AWP_Mega » 30-07-2009 19:18:17

ai2_movetoflag [персонаж] [номер точки]
ну не как не работает да и ai2_attack 1 2
                ai2_movetoflag 1 flag дело даже не в ошибке постановки команды в скриптах,не работает нигде,есть ли команда,которая нормально отправляет персонажа к флагу

geyser » 30-07-2009 22:02:41

Нда, вот что называется "два сапога - пара"...

@ AWP:
Тупишь, батя. Большинство команд обращаются к персам не по индексу, а по имени.

@ Mih@:
Тупишь, батя. Как можно писать пособие по скриптам без типа входных параметров?

AWP_Mega » 31-07-2009 07:44:18

geyser написал(а):

Тупишь, батя. Большинство команд обращаются к персам не по индексу, а по имени.

Спасибо,знаю,ты меня не так понял,это не индексы,это номера(типа persona}!{ 1 and persona}!{ 2)

geyser » 31-07-2009 10:40:14

AWP, букву "}!{" - отставить. НЕМЕДЛЕННО. Это и в первый раз было не смешно, а сейчас и подавно. Ты ведь не используешь подобные символы в именах персов? Не используешь. И неча, ну НЕ-ЧА, насиловать мне мозги. Да и самому себе. Ты как Миха, честное слово. Половина твоих бед - надуманные.
И второе. Тормозной траблшутинг - отставить. НЕМЕДЛЕННО. Если лохи имеют кое-какое право тормозить, рапортуя о проблемах, то ты такого права уже давно не имеешь. Хоть в аську пиши в конце концов (см. ЛС), там я из тебя клещами вытяну контекст вызова твоих команд. А на форуме будет спокойнее.

AWP_Mega » 31-07-2009 11:22:39

Хорошо,правда пишу в личку Михе(тебе предпочитаю писать по более серьезным проблемам,или по ресурсам,пока проблем не вижу,да и OUPом пользуюсь чаще,чем сплитом)а он и не думает отвечать,Миха ты личку проверяй пожалуйста,ведь не все мысли мне на форуме излагать,а Ж пишу как привык,лень раскладку туда-сюда щелкать,а вот по вопросам даже стыдно в icq обращаться,какой раз что-либо в скриптах не работает,потом целый день проверяю,и выясняется что в катсцене всего-то в func void ошибки..

geyser » 31-07-2009 12:48:07

Если обратишься сразу, то и решение получишь быстрее, и опыт скорее приобретёшь, и перестанешь ошибаться.
А вообще попробуй осознать, что моддинг - это как любая точная наука. Никакой мистики, да и глюков - мало.
Поэтому если ты чего-то хочешь, и не получается, то надо лишний раз проверить, как именно ты отдал приказ.
Проверить синтаксис, это само собой. А ещё помогает - искать проблему методом урезания функциональности.
Если у тебя есть подозрение, что в твоём могучем скрипте что-то не так, есть смысл упростить его до предела.
Такие минимальные примеры запросто можно постить на форуме целиком, и гуру будут только рады помочь...
Главное, чтобы ты сам рассуждал логически и понимал, что для твоего скрипта - принципиально, а что - нет.
Если ты не умеешь мыслить модулярно, то ты видишь только отдельные команды или весь гигантский скрипт.
А важно именно уметь быстро изъять из скрипта все элементы, относящиеся или не относящиеся к проблеме.

"а Ж пишу как привык,лень раскладку туда-сюда щелкать"
Меня твоя лень и привычки мало интересуют. Насиловать синтаксис - последнее дело. Пиши транслитное "zh".

Мih@ » 31-07-2009 14:55:25

geyser написал(а):

Тупишь, батя. Как можно писать пособие по скриптам без типа входных параметров?

можно. как в неокончательную версию. уточнения только в плане "номер персонажа"/"имя персонажа"/"персонаж". там, где не уточнено, на данный момент лучше просто глянуть dump_docs или вику. позже можно привести "персонаж" в значение "возможны оба варианта". как минимум. раз типы принципиальны и неочевидны - потом пофиксю по всему посту сразу, ок.

AWP_Mega написал(а):

Миха ты личку проверяй пожалуйста

я вижу.

s/persona}!{/nEpCoHa}|{/g s/persona}!{/person/g

doktordulit » 22-10-2009 18:50:36

Может кому-нить будет интересно:
Как мы все знаем,в ониных скриптах нельзя генериривать случайные числа.На английском форуме Leus спросил:
"Разве совсем нет методов добывания рандомных(случайных) чисел в они?"на что последовал ответ Gumby:

Код:

int i = 1;
max_i = 10;
void random_gen() {
i = i+1;
if(i > max_i) i = 1;
sleep 1;
fork random_gen
}

Если кому не понятно,то обьясню.
Каждый фрэим из этои функции выходит новое число(новое i).

Мih@ » 23-10-2009 06:28:32

doktordulit написал(а):

Как мы все знаем,в ониных скриптах нельзя генериривать случайные числа.

кагбэ этот же метод и в OTA давно используется. модуль юникстайма своими руками. ) никаких чисел из функции не выходит, просто в каждый фрейм времени i оказывается равным новому псевдослучайному числу.
раз запостил в эту тему, имеешь ввиду, что стоит добавить в первый пост? я этот рандом в global вижу примерно так:
var int myintrnd = 0;
var bool dogen = 1;
func void random_gen(int sstep, int rndmax)
{
    myintrnd = myintrnd + 1;
    if (myintrnd > rndmax) myintrnd = 1;
    sleep (sstep);
    if (dogen) fork random_gen(sstep, rndmax);
}

с учётом того, что можно для каждого параллельного счётчика кроме myintrnd либо написать вторую аналогичную функцию, либо внести её сюда же вместе с дополнительным max-аргументом. в случае, если шаг времени для всех един. значение "0" оставлено на случай, если генератор не был запущен вообще.
а вообще, рандом слишком от контекста зависим, единственное преимущество такого варианта - что его можно смело запускать с самого начала и сразу убить стек учесть в ослучаивании точную продолжительность wait_to_key.

FordFocusII » 25-11-2009 09:17:42

Люди а есть скрипт чтобы сделать боту регенирацию?

BUM » 21-02-2010 18:37:59

Ребят потскажите можно ли как-то сделать чтоб у муро-мутанта(когда ты за него играеш) был телекинез??
Просто у мукада можно было забиндить его шар самоновадящися...

Димидиран » 22-02-2010 13:05:04

а как сделать чтобы Барабас бил только дрожью земли?

AWP_Mega » 11-05-2010 14:39:03

Димидиран написал(а):

а как сделать чтобы Барабас бил только дрожью земли?

Зациклить одну и ту же анимацию на короткий sleep,тогда ты к нему и подойти не сможешь.

BUM написал(а):

Ребят потскажите можно ли как-то сделать чтоб у муро-мутанта(когда ты за него играеш) был телекинез??

Как такого-да,через скрипты-нет.

BUM написал(а):

Просто у мукада можно было забиндить его шар самоновадящися...

С какого перепуга у Мукада самонаводящиеся шары,да и с каких пор их можно биндить?

demos_kratos » 11-05-2010 17:48:35

Забиндить их нельзя. Можно только заменить следующим образом:

Код:

func void replmuk(void)
{
    chr_wait_animation 0 NINCOMpunch_heavy
    chr_animate 0 NINCOMfireball
    fork replmuk
}
NiKiT@ » 13-07-2010 23:42:29

demos_kratos написал(а):

Забиндить их нельзя. Можно только заменить следующим образом:

Код:

func void replmuk(void)
{
    chr_wait_animation 0 NINCOMpunch_heavy
    chr_animate 0 NINCOMfireball
    fork replmuk
}

как это нельзя? Кнопки ф2 и ф3 как раз созданы для того чтобы записать на них любые анимации! На них можно
забайндить любые анимации.
Надо просто положить
название анимации в
переменную sc_bind_f2 или
sc_bind_f3. В key_config.txt
должно быть прописано,
например, bind fkey2 to
cutscene1 и bind fkey3 to
cutscene2
з.ы. Но и с твоим вaриaнтом d_k я тожe соглaсeн!

Мih@ » 14-07-2010 01:37:54

NiKiT@ написал(а):

как это нельзя?

на маке нельзя. возможно, до сих пор. :3
плюс нюанс, что работать оно будет только при записи film'а.
минус то, что биндить можно не только на fkey2 и fkey3.

NiKiT@ » 14-07-2010 10:00:03

Оххх....сори...забыл сказать про запись film'ов, спасибо что поправил =)

Smith » 23-08-2010 11:21:08

Народ напомните плиз сайт со списком всех персонажей в уровнях (с картинки и характеристики), дверей, и флагов))

demos_kratos » 25-08-2010 19:58:54

http://ssg.oni2.net

Гордон Фриман » 03-09-2010 08:26:22

Миха, плиз, скажи скрипт, что бы когда я создавал вторую, третью и т.д... коноку, управление на неё не переключалось, а осталось на первой, а новая просто помогала первой. А то так нашлёпал 10 барабасов, захотел 10 конок (ну, супер стрелку устроить:)), создал новую, а управление переключилось на неё, а камера на первой осталась. Помоги плиз. Ты как то это сделал, вот тут -  http://onimia.ru/doc/game_gallery_res.php?6

Интересно, а как ты вот это сделал, ну приёмы  партикли поменял, тоже круто - http://onimia.ru/doc/game_gallery_res.php?10
Вот это сделал данными скриптами, конечно с бесконечными патронами оружие просто супер стреляет, особенно крикун понравился, и плазменная пушка:) тока не удобно ходить, и если рядом враги, без кода бессмертия не обойтись, поскольку время то в игре раз в 500 ускоряется, и ты не успеваешь кнопку нажать, как уже мёртвый валяешься:) но спасибо - http://onimia.ru/doc/game_gallery_res.php?12

Ну и наконец, это тоже круто - http://onimia.ru/doc/game_gallery_res.php?1

Мih@ » 03-09-2010 11:45:06

Гордон Фриман написал(а):

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

по идее так и должно быть. особенно если создаёшь через ai2_spawn.
если нет, chr_focus в помощь. нумерация в порядке спавна, 0 всегда 0.

Гордон Фриман написал(а):

Ты как то это сделал, вот тут

это не я, а Амэ делала. к тому же, в данном случае, скорее всего, в кадре и есть управляемый персонаж, а камера стоит на месте за счёт cm_detach, например.

Гордон Фриман написал(а):

Интересно, а как ты вот это сделал, ну приёмы  партикли поменял

это к скриптам не относится. man ONCC; ONCP.

Гордон Фриман написал(а):

поскольку время то в игре раз в 500 ускоряется

ну дык это для красоты, а не для практического применения.

Гордон Фриман » 03-09-2010 13:14:35

Тоесть я создаю коноку, и что бы с неё вернуть управление, набираю chr_focus 0? А создаю я её в начале био лаб. скриптом ai2_spawn konoko force . Когда она появляется я начинаю ей управлять, но камера на первой остаётся. Получается скрипт который ты дал избавляет от этой проблемы? :dunno:

Smith » 27-09-2010 10:31:30

Народ, как остановить функцию вызванной камандой "fork" ?? (Чтобы команда перестала выполнятся)

NiKiT@ » 27-09-2010 14:57:35

Помоему - никак)

Smith » 04-10-2010 12:12:51

А кто знает, как изменить скорость полёта пули?? (оружия)

NiKiT@ » 04-10-2010 15:58:58

я знаю)

Smith » 04-10-2010 16:00:32

NiKiT@ написал(а):

я знаю)

=) Куль. Ну и как изменить?

NiKiT@ » 05-10-2010 14:24:24

Мммм...на форуме ответ то есть!)
в файле ONWC по адресу 0x21E находится задержка между выстрелами в фреймах в формате int16
по адресу 0x220 находится задержка, испльзуемая при активации чит-кода "roughjustice"

это если оружие использует только один партикль. если не один, то придётся искать среди массивов партиклей нужный и относительно него эти данные находятся по адресам 0x046 и 0x048 соответственно.

Smith » 05-10-2010 14:56:17

NiKiT@ написал(а):

Мммм...на форуме ответ то есть!)
в файле ONWC по адресу 0x21E находится задержка между выстрелами в фреймах в формате int16
по адресу 0x220 находится задержка, испльзуемая при активации чит-кода "roughjustice"

это если оружие использует только один партикль. если не один, то придётся искать среди массивов партиклей нужный и относительно него эти данные находятся по адресам 0x046 и 0x048 соответственно.

Спасибо за инфу Никит)) Но я имел ввиду немножко другое: скорость полёта пули, а не скорострельность оружия))

NiKiT@ » 05-10-2010 15:17:42

ааа...ну этого я точно не знаю) Помоему можно!

Smith » 05-10-2010 15:21:25

NiKiT@ написал(а):

ааа...ну этого я точно не знаю) Помоему можно!

Да, жаль... А силу атаки персонажа (конока или другие) как настроить? Тоесть кол-во хп отнимающиеся при ударах и бросках.

NiKiT@ » 05-10-2010 17:59:35

Ааа.. я как-то это делал)
Читал тут: http://wiki.oni2.net/ONCC

Smith » 05-10-2010 18:59:49

NiKiT@ написал(а):

Ааа.. я как-то это делал)
Читал тут: http://wiki.oni2.net/ONCC

Да, я знаю про ONCC, просто если ты помнишь то скажи строку=)))

NiKiT@ » 06-10-2010 17:37:04

Если не ошибаюсь, то вначале после рисунка строки:
0x020  float  00 00 34 42  45.000000  maximal falling height without damage 
0x024  float  00 00 07 43  135.000000  maximal falling height with damage

Smith » 06-10-2010 18:13:38

NiKiT@ написал(а):

Если не ошибаюсь, то вначале после рисунка строки:
0x020  float  00 00 34 42  45.000000  maximal falling height without damage 
0x024  float  00 00 07 43  135.000000  maximal falling height with damage

Нее( Это характеристики падения игрока с высоты 45 - падение без повреждений) и начиная с 135 - смертельная=)

NiKiT@ » 07-10-2010 10:58:42

Ну тогда х.з

demos_kratos » 08-10-2010 14:44:30

Данные об уроне приемов вроде хранятся в самих TRAMах. А их сложновато редактировать.

Smith » 08-10-2010 14:58:58

demos_kratos написал(а):

Данные об уроне приемов вроде хранятся в самих TRAMах. А их сложновато редактировать.

спс) а скорость полёта пули можно вообще регулировать? (не путать с скорострельностьтю оружия) ??

да и ещё: можешь рассказать что значит <Weight>80</Weight> в Melee ресурсах, и как там именуются супер удары? Львиная лапа, калесо дьявола, Сокрушители, болда и прочее...

demos_kratos » 08-10-2010 15:19:43

Скорость полета пули рекулируется в файле партикля пули (если точнее, то BINA/PAR3). Партикли редактировать тоже не мёд =)

Про weight. Попробуй изменить и запихнуть в игру и посмотри что получится. Я не пробовал еще.

Про суперудары. Все обозначения анимаций есть тут - http://wiki.oni2.net/Combat_moves
В частности анимации суперударов обозначаются ******kick(punch)_heavy

Smith » 08-10-2010 15:59:30

demos_kratos написал(а):

Скорость полета пули рекулируется в файле партикля пули (если точнее, то BINA/PAR3). Партикли редактировать тоже не мёд =)

Про weight. Попробуй изменить и запихнуть в игру и посмотри что получится. Я не пробовал еще.

Про суперудары. Все обозначения анимаций есть тут - http://wiki.oni2.net/Combat_moves
В частности анимации суперударов обозначаются ******kick(punch)_heavy

Спасибо за инфу=) А у тебя есть какие-нибуть собственные моды, скриптовые сценки и.т.д ?

NiKiT@ » 08-10-2010 18:35:58

demos_kratos написал(а):

Данные об уроне приемов вроде хранятся в самих TRAMах. А их сложновато редактировать.

Оппа)) Спасибо за инфу, покопаемся)

kvodon » 10-12-2010 19:10:54

Подскажите что делать
когда я делаю какие либо изменение в скриптах
то при запуске игры врагов почти нет а появляешься в любом случае в самом начале игры

MyKa4eB0 » 10-12-2010 19:16:31

это значит, что твои скрипты вызывают у движка недоумение, т.е. либо они ошибочны, либо чего-то не хватает, ибо менять еще нужно уметь. но FAQ в данной тебе составлен очень классно, подробно, по-этому даже я понял)

kvodon » 11-12-2010 17:36:16

я использовал целые команды из вышсказаной статьи таже фигня

Гордон Фриман » 13-12-2010 04:28:05

Я вот заметил, что некоторые враги появляются на уровне, даже если нет скриптов, при этом они полностью работоспособны. Получается есть боты, стандартно включенные в игру?

kvodon » 13-12-2010 13:14:55

estanol написал(а):

Санчо панчо, у мну такая же вата была. исправляется так, тебе тупо должны скинуть этот файл water.pcf и да кстате попробуй приканектится, тебе вылетет эта ошибка, потом опять открой кансоль и там должно быть написано что не хватает еще нескольких файлов такого типа, у мну так было. напиши точные названия этих файлов и пусть те кто нить их зальет. потом просто замени их и все.

спасибо попробую

Гордон Фриман » 06-01-2011 15:32:00

Мih@ написал(а):

chr_set_class [имя персонажа] [класс]
Задаёт персонажу класс - ONCC в ресурсах, содержащий все физические данные и ссылки на них, включая модель, текстуры, набор анимаций, и т.п. Имя, АИ и всё прочее остаётся прежним.

Миха, у тебя ошибка в пособии. На эту команду не влияет имя персонажа, нужно ставить номер перса на уровне! Я уже 2 дня не могу найти номер перса Floor2_Striker_3  на био лаборатории. Имена эта команда не распознает. А номера только наугад. Ты сам это как делал?

Мih@ » 06-01-2011 16:33:39

Гордон Фриман написал(а):

Миха, у тебя ошибка в пособии.

ага, поправил. называется это дело типом параметров функции. в принципе, все строки, где указано просто [персонаж], тоже завуалированные ошибки (где-то имя, где-то номер, где-то перегрузка, которая и подразумевается), надо всё это дело уточнять. и не только это.

Гордон Фриман написал(а):

А номера только наугад. Ты сам это как делал?

номер персонажу присваивается в порядке спавна, начиная с игрока под номером 0. возможность "освобождения" номеров для новоспавненных чаров путём полного удаления старых уже обсуждалась... где-то. суть в том, что да - просто так сходу номер зачастую определить сложно, и выход здесь довольно однозначен - использующий номера скрипт должен быть по возможности более детерминирован в плане порядка и количества спавнов, и все вариации нужно подсчитывать (в общем-то одного int, подсчитывающего "текущий" номер, обычно вполне хватает, остальное элементарными флажками делается).

MyKa4eB0 » 07-01-2011 07:40:23

Мih@ написал(а):

номер персонажу присваивается в порядке спавна, начиная с игрока под номером 0.

Это по идее с учетом тех, которые есть на уровне, но по какой-то причине не были спавнены? То есть они прописаны в файле уровня, но их нет на уровне, пока не введешь ai2_spawnall

Мih@ » 07-01-2011 07:45:53

MyKa4eB0 написал(а):

Это по идее с учетом тех, которые есть на уровне, но по какой-то причине не были спавнены?

нет.

Гордон Фриман » 07-01-2011 12:16:02

Номера в порядке спавна... Странно, получается тот кого я ищу должен быть на отрезке от 3 до 5, но под этими номерами он не числится.

Мih@ » 07-01-2011 13:34:37

Гордон Фриман написал(а):

Странно, получается тот кого я ищу должен быть на отрезке от 3 до 5, но под этими номерами он не числится.

можно проверить непосредственно в игре - например, подходишь и в консоли пишешь who; печатаются имена, классы и номера всех близрасположенных чаров.
вполне могут сбивать счёт персонажи, заспавненные заранее, по триггерам, таймерам и т.п.: к примеру, в начале шестой главы, едва поднимаясь на второй этаж гаража, можно сразу познакомиться с #5~#8 чарами, минуя #1~#4. +)

Гордон Фриман » 07-01-2011 14:33:31

Спасибо, но я делаю мод для био лаборатории, и выработал свой алгоритм высчитывания номера. Несколько проще но тоже действенный.

elex » 08-01-2011 20:23:14

Маловероятно но всёже, может кто подскажет можно ли скриптом создать в Они стрелочку как в гта, которая подпрыгивает, объкт на карте я создам, а как его анимировать?

Мih@ » 08-01-2011 21:09:59

elex написал(а):

стрелочку как в гта

<libastral=enabled>нечто вроде жёлтого objective-кружочка (objective_set) в самой Оньке?</libastral> скорее всего, можно, но скриптовая часть будет заключаться только в вызовах obj_create и obj_kill в нужные моменты. или particle(, create|kill|start|stop|etc.). всё, что нужно - номера/названия этих сущностей и сама их суть.
анимация может быть двух видов - или движется в пространстве сам объект/частица, или на статичную плоскость нужно положить анимированную (построенную из кучки кадров, ага, man TXAN) текстуру. как это делается или хотя бы по какому пути идти проще (объекты ж не из 19 кусков состоят, а просто крутятся и ездиют), понятия не представляю, вопрос далеко не скриптовый. +)

elex » 08-01-2011 21:46:18

Мih@ написал(а):

объекты ж не из 19 кусков состоят, а просто крутятся и ездиют), понятия не представляю, вопрос далеко не скриптовый.

Открывание дверей чем сделано(я про автоматические двери которые открываются при приближении)? Дверь отдельный меш, какая разница, дверь будет елозить вверх вниз или меш названный дверью, просто как сделать чтобы вверх вниз курсировал сабж? Частицы не подойдут, у них время существования ограничено по времени

Добавлено спустя 1 минуту 46 секунд:
Ладно, чёрт с ней со стрелочкой, открывание двери как реализовать?

Мih@ » 08-01-2011 22:03:42

elex написал(а):

Ладно, чёрт с ней со стрелочкой, открывание двери как реализовать?

скриптами - door_open номер_двери
чтобы елозило - зациклить: то door_open, то door_close. предварительно заперев через door_lock.
из игры - к двери привязан квадратный триггер, по которому она может открываться без ctrl, если снят соответствующий бит.

двери могут открываться и горизонтально, и вертикально, и вокруг оси (как в Омегу, например). man BINA/OBJC/DOOR, man DOOR, там должна быть ссылка на OBAN, описывающий движение объекта. если я всё правильно понимаю. ><

Гордон Фриман » 09-01-2011 16:37:18

А какой командой можно привязать какое-либо действие к  смерти того или иного перса?

Мih@ » 09-01-2011 17:31:11

Гордон Фриман написал(а):

А какой командой можно привязать какое-либо действие к  смерти того или иного перса?

man BINA/CHAR; man chr_wait_health

Гордон Фриман » 09-01-2011 17:39:01

Пасиб.

elex » 10-01-2011 11:08:29

Мih@, спасибо за пояснения

подскажите как таймер заставить работать? и как его выключить?
#
# Testing.bsl
#

func void
main(
    void)
{
    env_shade 1500 1501 .9 .8 .9
    gl_fog_blue=0
    gl_fog_red=0
    gl_fog_green=0
    gl_fog_start=.975
    gs_farclipplane_set 900
    start
    if (my_save_point eq 0)
    {
        timer_start 60 lose
    }
    env_show 31 0
    env_show 41 0
}

Мih@ » 10-01-2011 12:25:51

elex написал(а):

подскажите как таймер заставить работать? и как его выключить?

вообще-то в оппосте пунктом 2.8 всё что нужно написано. +)
для тестов можно начать с более лаконичного варианта:
func void main(void)
{
    if (save_point eq 0) timer_start 10 lose
}


во-первых, для проверки загруженного сейвпоинта используется переменная save_point (sic!). my_save_point - это просто традиционно используемое разработчиками название переменной для разных скриптовых целей.
во вторых, на всякий случай, start - это тоже просто традиционная функция для дефолтных скриптов. изначально таковой не существует. )
отключается таймер или по завершении отсчёта, или по timer_stop, к примеру:
func void main(void)
{
    if (save_point eq 0)
    {
        timer_start 5 lose
        fork waitforanim
    }
    sleep 360
    win
}
func void waitforanim(void)
{
    chr_wait_animation 0 KONCOMkick_heavy
    timer_stop
}

elex » 10-01-2011 17:24:16

Мih@ , шикарно, работает именно так как нужно, отбрасывает в точку появления, огромное спасибо. А счётчик времени(просто считает затраченное время) можно сделать?

Добавлено спустя 1 минуту 33 секунды:
я уровень5 the airport part deux ковыряю, там нет ничерта кроме скайбокса, с существующими уровнями пока не могу запихать обратно сохранив координаты(руки кривые у меня)

Мih@ » 10-01-2011 18:07:05

elex написал(а):

А счётчик времени(просто считает затраченное время) можно сделать?

чтобы он считал также, как таймер, но в обратную сторону - вряд ли. можно сделать просто счётчик и выводить циферки обычным dmsg. например:

var bool count_stop = 0;
var int count_var = 0;
func void main(void)
{
    fork counting(60);
    sleep 1800
    count_stop = 1
}
func void counting(int count_step)
{
    sleep(count_step);
    if (!count_stop)
    {
        count_var = count_var + 1
        dmsg_int(count_var);
        fork counting(count_step);
    }
}
func void dmsg_int(int messaga)
{
    if (messaga eq 0) dmsg "0"
    if (messaga eq 1) dmsg "1"
    if (messaga eq 2) dmsg "2"
    if (messaga eq 3) dmsg "3"
    if (messaga eq 4) dmsg "4"
    if (messaga eq 5) dmsg "5"
    if (messaga eq 6) dmsg "6"
    if (messaga eq 7) dmsg "7"
    if (messaga eq 8) dmsg "8"
    if (messaga eq 9) dmsg "9"
    if (messaga eq 10) dmsg "10"
    if (messaga eq 11) dmsg "11"
    if (messaga eq 12) dmsg "12"
    if (messaga eq 13) dmsg "13"
    if (messaga eq 14) dmsg "14"
    if (messaga eq 15) dmsg "15"
    if (messaga eq 16) dmsg "16"
    if (messaga eq 17) dmsg "17"
    if (messaga eq 18) dmsg "18"
    if (messaga eq 19) dmsg "19"
    if (messaga eq 20) dmsg "20"
    if (messaga eq 21) dmsg "21"
    if (messaga eq 22) dmsg "22"
    if (messaga eq 23) dmsg "23"
    if (messaga eq 24) dmsg "24"
    if (messaga eq 25) dmsg "25"
    if (messaga eq 26) dmsg "26"
    if (messaga eq 27) dmsg "27"
    if (messaga eq 28) dmsg "28"
    if (messaga eq 29) dmsg "29"
    if (messaga eq 30) dmsg "30"
    if (messaga eq 31) dmsg "31"
    if (messaga eq 32) dmsg "32"
    if (messaga eq 33) dmsg "33"
    if (messaga eq 34) dmsg "34"
    if (messaga eq 35) dmsg "35"
    if (messaga eq 36) dmsg "36"
    if (messaga eq 37) dmsg "37"
    if (messaga eq 38) dmsg "38"
    if (messaga eq 39) dmsg "39"
    if (messaga eq 40) dmsg "40"
    if (messaga eq 41) dmsg "41"
    if (messaga eq 42) dmsg "42"
    if (messaga eq 43) dmsg "43"
    if (messaga eq 44) dmsg "44"
    if (messaga eq 45) dmsg "45"
    if (messaga eq 46) dmsg "46"
    if (messaga eq 47) dmsg "47"
    if (messaga eq 48) dmsg "48"
    if (messaga eq 49) dmsg "49"
    if (messaga eq 50) dmsg "50"
    if (messaga eq 51) dmsg "51"
    if (messaga eq 52) dmsg "52"
    if (messaga eq 53) dmsg "53"
    if (messaga eq 54) dmsg "54"
    if (messaga eq 55) dmsg "55"
    if (messaga eq 56) dmsg "56"
    if (messaga eq 57) dmsg "57"
    if (messaga eq 58) dmsg "58"
    if (messaga eq 59) dmsg "59"
    if (messaga eq 60) dmsg "60"
    if (messaga eq 61) dmsg "61"
    if (messaga eq 62) dmsg "62"
    if (messaga eq 63) dmsg "63"
    if (messaga eq 64) dmsg "64"
    if (messaga eq 65) dmsg "65"
    if (messaga eq 66) dmsg "66"
    if (messaga eq 67) dmsg "67"
    if (messaga eq 68) dmsg "68"
    if (messaga eq 69) dmsg "69"
    if (messaga eq 70) dmsg "70"
    if (messaga eq 71) dmsg "71"
    if (messaga eq 72) dmsg "72"
    if (messaga eq 73) dmsg "73"
    if (messaga eq 74) dmsg "74"
    if (messaga eq 75) dmsg "75"
    if (messaga eq 76) dmsg "76"
    if (messaga eq 77) dmsg "77"
    if (messaga eq 78) dmsg "78"
    if (messaga eq 79) dmsg "79"
    if (messaga eq 80) dmsg "80"
    if (messaga eq 81) dmsg "81"
    if (messaga eq 82) dmsg "82"
    if (messaga eq 83) dmsg "83"
    if (messaga eq 84) dmsg "84"
    if (messaga eq 85) dmsg "85"
    if (messaga eq 86) dmsg "86"
    if (messaga eq 87) dmsg "87"
    if (messaga eq 88) dmsg "88"
    if (messaga eq 89) dmsg "89"
    if (messaga eq 90) dmsg "90"
    if (messaga eq 91) dmsg "91"
    if (messaga eq 92) dmsg "92"
    if (messaga eq 93) dmsg "93"
    if (messaga eq 94) dmsg "94"
    if (messaga eq 95) dmsg "95"
    if (messaga eq 96) dmsg "96"
    if (messaga eq 97) dmsg "97"
    if (messaga eq 98) dmsg "98"
    if (messaga eq 99) dmsg "99"
    if (messaga > 99) dmsg "IT'S OVER 9000"
}

elex » 10-01-2011 18:33:36

Оно самое, fork counting(60); - точность отсчёта насколько понял, увеличив в 10 раз будет считать по 10 секунд, ещё раз спасибо.

На сегодня всё, левая кнопка у мыши провалилась, теперь завтра продолжу :(

Гордон Фриман » 11-01-2011 15:45:30

Скажите плиз имя мелодии для скрипта так называемых душераздирающих скрипочек из 12 уровня.

Гордон Фриман » 04-02-2011 08:29:47

Большое спасибо :pleasantry:  Может тогда расскажете как пользоваться командой man BINA/CHAR; man chr_wait_health

Мih@ » 04-02-2011 10:00:39

Гордон Фриман написал(а):

Большое спасибо :pleasantry:

а то, всегда рады помочь.

Гордон Фриман написал(а):

Может тогда расскажете как пользоваться командой man BINA/CHAR; man chr_wait_health

берёшь моск, читаешь вот это. желательно тщательно и несколько раз, но особенное внимание обратить вот эти строки:
0x0C8 script function called when character is spawned
0x0E8 script function called when character dies (health reaches 0); can work multiple times
0x108 script function called when character notices an enemy; works only once
0x128 alarm function; never used in Oni, it is called when character is alarmed
0x148 script function called when character is hurt for the first time; works only once
0x168 script function called when character is "defeated" (health reaches 1); works only once
0x188 script function called when character runs out of ammo (reloads a weapon with the last clip/cell); works only once, and the character must have the ammo at spawn-time
0x1A8 nopath function, some exotic script function call ("should" be called when a character has trouble pathfinding, but isn't)

если просветление не достигнуто - читаешь первый пост, особенно пункты 4.4 и 1.2.3. вслух, с выражением.
учишься задавать вопросы в положенном месте, а не где попало.

Гордон Фриман » 04-02-2011 10:21:13

Мih@ написал(а):

учишься задавать вопросы в положенном месте, а не где попало.

А мне казалось, что про скрипты нужно именно здесь вопросы задавать...

Мih@ » 04-02-2011 11:26:14

Гордон Фриман написал(а):

А мне казалось, что про скрипты нужно именно здесь вопросы задавать...

нет.

Гордон Фриман » 04-02-2011 13:34:04

Тогда где, в теме кто где живет?

Мih@ » 04-02-2011 14:43:28

Гордон Фриман написал(а):

Тогда где, в теме кто где живет?

раз, два, три - из очевидного. здесь - только обсуждение/дополнения к первому посту (уже постам). если бы не обыденная толерантность к флуду, других бы постов тут и не было, а за вопросы на тему звуков посылали бы очень-очень далеко.

Гордон Фриман » 05-02-2011 14:46:29

Окей кэп

Простофиля » 07-07-2011 09:37:03

Гордон Фриман написал(а):

Окей кэп

ГОРДАн ФРиМен ! кАК УБИТЬ В HL боследнего боса???

Гордон Фриман » 21-12-2011 05:47:58

Молча

NerrO » 27-12-2011 17:50:06

Спасибо за тему! Буду учиться :yahoo:

Sfeli » 15-08-2012 13:33:29

Несколько деталей про планировщик...

fork dmsg "test" – работает, но число аргументов не проверяет
fork chr_wait_animation 0 boo – валится: SLrSchedule_Function_Engine банально передаёт NULL вместо UUtBool * defer, вызывая функцию
перед форком (пытаясь его избежать)
schedule chr_wait_animation(0, "boo") at 0 – валится по тому же поводу, что и предыдущая; а вот с ненулевой задержкой (at 1) уже работает
schedule dmsg("test") at 100 – работает, как и должно
schedule did_kill_griffen at 1 – валится, как и любая другая встроенная функция, возвращающая не void (fork did_kill_griffen, естественно, тоже).
schedule dmsg("test") repeat 3 every 100 Несмотря на проблемы с  at 0 выше, выражение every 0 работает, потому что движок не может избежать создания задачи из-за наличия repeat.


Кто помнит что-нибудь ещё, связанное с wait-функциями, fork, schedule, repeat и т. п.? Пока лимиты в расчёт не берём, и про игнор repeat вне выражения schedule я знаю.

Николай » 03-05-2013 10:00:26

Боже, сколько же здесь написано...

Worm » 06-12-2013 16:40:29

Привет! слушай, как то пытался разобраться во всем этом, но терпения не хватило. не можешь подсказать, есть ли возможность просто закрепить эффект от кода carousel (замедленный режим) за нажатием какой нибудь одной кнопки?

Cfif » 07-12-2013 17:10:19

Worm написал(а):

Привет! слушай, как то пытался разобраться во всем этом, но терпения не хватило. не можешь подсказать, есть ли возможность просто закрепить эффект от кода carousel (замедленный режим) за нажатием какой нибудь одной кнопки?

Я точно знаю что можно забиндить приемы на отдельные кнопки. Только это не слишком просто и проще делать их самому (я это узнавал еще лет 5-6 назад, когда на старой убогой клавиатуре не мог сделать полумесяц). А вот закреплять коды... даже не знаю.

Глебс » 08-11-2014 10:06:01

Добавлю к основному списку эти команды. Помимо имеющихся, эти самые нужные из всех.
chr_freeze [персонаж] [1 или 0], где при 1 "отупляет" персонажа. 0 возвращает ум. Или chr_neutral  [персонаж] [1 или 0]
chr_inv_reset [персонаж] - очищает инвентарь.(оружие, гипо, патроны и т.д.)
ai2_chump [персонаж] - создает персонажа для поиска пути.
ai2_chump_stop=1 - останавливает его
ai2_noncombatant [персонаж] [1 или 0] - при 0 персонаж умеет драться, а при 1 начинает вести себя как цивилы
ai2_reset - возвращает всем персонажам на уровне их базовые настройки
ai2_setalert [персонаж] [alert] - устанавливает уровень встревоженности. alert может быть:lull-спокойствие low-низкий medium-средний high-высокий combat-боевой
chr_disable_melee [1 или 0] - то же самое, что и чит canttouchthis, но броски/разоружения/захваты делать можно + при обычных ударах(не бросках и т.д. ) не наносится урон
chr_enable_collision [1 или 0] - при 0 все персонажи станут нематериальны
chr_full_health [персонаж] - повышает здоровье до планки. У каждого персонажа своя "планка"
chr_poison ([персонаж], [урон], [интервал], [начальный интервал]) - отнимает здоровье в зависимости от параметров
chr_weapon_immune [персонаж] - делает персонажа невосприимчивым к оружию
gs_show_corpses [1 или 0] - Показывает или скрывает трупы. При 1 показывает, при 0 нет. Но только те трупы, которые есть на уровне с самого начала
cutscene_sync [mark/on/of] - маркирует точку в катсцене
door_ignore_locks - разблокирует все двери
reset_mechanics - сбрасывает все на уровне (триггеры, туррели, консоли, и т д...) в исходное состояние
chr_draw_weapon [1 или 0] - при 1 показывает оружие, при 0 нет
ai2_report [персонаж] - показывает информацию о персонаже(job, current etc) или ai2_report_verbose [персонаж]
gs_show_particles [1 или 0] - при 1 показывает все частицы, при 0 скрывает
p3_startall - стартует все уровневые частицы
p3_stopall - останавливает все уровневые частицы